尝试构建用于提取数据的TCP服务器

时间:2017-11-20 15:16:20

标签: php tcp raspberry-pi

我正在尝试构建一个系统来替换我们现有的系统。它是一个音频流媒体系统。当前系统具有封闭的源程序,该程序在摄取数据和音频的PC上运行。我正在使用覆盆子pi和TCP数据来尝试替换当前系统。客户端将数据发送到pi,pi将获取数据并将其记录下来。

我理解它的方式,理论上,它的工作方式是客户端与服务器建立连接。然后,客户端可以通过该连接发送数据,直到它断开连接或连接出现问题。

客户端可以根据需要继续发送数据。在我的情况下,每次字符数量是相同的,但似乎服务器获得第一位数据,然后基本上超时。然后客户端建立另一个连接,它获取该数据,超时并重复。

我知道这是因为发送数据的系统记录了它,客户端上将有10行,但服务器上只有5行。

这是我的代码,我在PHP中这样做是因为我对此更加满意,但是如果能让这个过程变得更简单,我会更改为python或其他东西。



#!/usr/bin/php -q 
<?php 
/** 
  * Listens for requests and forks on each connection 
  */ 

$__server_listening = true; 

error_reporting(E_ALL); 
set_time_limit(0); 
ob_implicit_flush(); 
declare(ticks = 1); 

become_daemon(); 

/* nobody/nogroup, change to your host's uid/gid of the non-priv user */ 
//change_identity(1000, 1000); 

/* handle signals */ 
pcntl_signal(SIGTERM, 'sig_handler'); 
pcntl_signal(SIGINT, 'sig_handler'); 
pcntl_signal(SIGCHLD, 'sig_handler'); 

/* change this to your own host / port */ 
server_loop("10.0.3.49", 9009); 

/** 
  * Change the identity to a non-priv user 
  */ 
function change_identity( $uid, $gid ) 
{ 
    if( !posix_setgid( $gid ) ) 
    { 
        print "Unable to setgid to " . $gid . "!\n"; 
        exit; 
    } 

    if( !posix_setuid( $uid ) ) 
    { 
        print "Unable to setuid to " . $uid . "!\n"; 
        exit; 
    } 
} 

/** 
  * Creates a server socket and listens for incoming client connections 
  * @param string $address The address to listen on 
  * @param int $port The port to listen on 
  */ 
function server_loop($address, $port) 
{ 
    GLOBAL $__server_listening; 

    if(($sock = socket_create(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
        echo "failed to create socket: ".socket_strerror($sock)."\n"; 
        exit(); 
    } 

    if(($ret = socket_bind($sock, $address, $port)) < 0) 
    { 
        echo "failed to bind socket: ".socket_strerror($ret)."\n"; 
        exit(); 
    } 

    if( ( $ret = socket_listen( $sock, 0 ) ) < 0 ) 
    { 
        echo "failed to listen to socket: ".socket_strerror($ret)."\n"; 
        exit(); 
    } 

    socket_set_nonblock($sock); 
    
    echo "waiting for clients to connect\n"; 

    while ($__server_listening) 
    { 
        $connection = @socket_accept($sock); 
        if ($connection === false) 
        { 
            usleep(100); 
        }elseif ($connection > 0) 
        { 
            handle_client($sock, $connection); 
        }else 
        { 
            echo "error: ".socket_strerror($connection); 
            die; 
        } 
    } 
} 

/** 
  * Signal handler 
  */ 
function sig_handler($sig) 
{ 
    switch($sig) 
    { 
        case SIGTERM: 
        case SIGINT: 
            exit(); 
        break; 

        case SIGCHLD: 
            pcntl_waitpid(-1, $status); 
        break; 
    } 
} 

/** 
  * Handle a new client connection 
  */ 
function handle_client($ssock, $csock) 
{ 
    GLOBAL $__server_listening; 

    $pid = pcntl_fork(); 

    if ($pid == -1) 
    { 
        /* fork failed */ 
        echo "fork failure!\n"; 
        die; 
    }elseif ($pid == 0) 
    { 
        /* child process */ 
        $__server_listening = false; 
        socket_close($ssock); 
        interact($csock); 
        socket_close($csock); 
    }else 
    { 
        socket_close($csock); 
    } 
} 

function interact($socket) 
{ 
    $buf = socket_read($socket, 2048, PHP_NORMAL_READ);

	echo $buf . "\n";

	$file = '/home/pi/nowplaying.log';

	// Open the file to get existing content
	$current = file_get_contents($file);
	// Append a new person to the file
	$current .= date('Y-m-d h:i:s') . ' ' . $buf . "\n";
	// Write the contents back to the file
	file_put_contents($file, $current);


    $station = substr($buf, 0, 6);
    $type = substr($buf, 14, 4);
    $artist = preg_replace('/\s+/', ' ', substr($buf, 48, 28));
    $title = preg_replace('/\s+/', ' ', substr($buf, 20, 28));
    $length = substr($buf, 80, 5);

    echo "Station is: " . $station . "\n";
    echo "Type is: " . $type . "\n";
    echo "Song is: " . $artist . " - " . $title . "\n";
    echo "Length is: " . $length . "\n";

    //postToServer($station, $type, $artist, $title, $length);
    //updateIceCastServer($station, $type, $artist, $title, $length);

} 

function postToServer($station, $type, $artist, $title, $length)
{

	$url = 'http://website.net/data/' . $station . '/';

	$data = array('artist' => $artist, 'title' => $title, 'type' => $type, 'length' => $length);

	// use key 'http' even if you send the request to https://...
	$options = array(
	    'http' => array(
	        'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
	        'method'  => 'POST',
	        'content' => http_build_query($data)
	    )
	);
	$context  = stream_context_create($options);
	$result = file_get_contents($url, false, $context);
	if ($result === FALSE) { echo 'failed'; }

	var_dump($result);

}

function updateIceCastServer($station, $type, $artist, $title, $length)
{
	$username = 'admin';
	$password = 'admin';

	$url = 'http://ice.mywebserver.net:8000/admin/metadata?mount=/' . $station . '&mode=updinfo&song=' . $artist . ' - ' . $title;
	$data = array('artist' => $artist, 'title' => $title, 'type' => $type, 'length' => $length);

	// use key 'http' even if you send the request to https://...
	$options = array(
	    'http' => array(
	        'header'  => "Authorization: Basic " . base64_encode("$username:$password"),
	        'method'  => 'POST',
	        'content' => http_build_query($data),
	    )
	);
	$context  = stream_context_create($options);
	$result = file_get_contents($url, false, $context);
	if ($result === FALSE) { echo 'failed'; }

	var_dump($result);

}
/** 
  * Become a daemon by forking and closing the parent 
  */ 
function become_daemon() 
{ 
    $pid = pcntl_fork(); 
    
    if ($pid == -1) 
    { 
        /* fork failed */ 
        echo "fork failure!\n"; 
        exit(); 
    }elseif ($pid) 
    { 
        /* close the parent */ 
        exit(); 
    }else 
    { 
        /* child becomes our daemon */ 
        posix_setsid(); 
        chdir('/'); 
        umask(0); 
        return posix_getpid(); 

    } 
} 

?>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我最终为此使用了netcat。用NC打开端口并传递传入的数据要简单得多。

对于我的情况,我最终获取了数据,并向微服务发送了curl请求以完成我需要做的事情。

这是我完成所有这些操作的最终脚本。我运行一个基本的cron作业以保持其运行。

#!/bin/bash

logfile=smdv2.sh.log
today=`date +%Y%m%d`

log=~/$today-$logfile

exec > >(tee -ai $log) && 2>&1

echo "Started listening on port 9000"

nc -klu 9000 | while read line
do
    if [ "$line" == '' ]; then
    echo "Recieved Blank Line, Skipping"
else
    echo "Recieved Line"
    echo $line
    cart=${line:6:7}
    type=${line:13:4}
    title=${line:19:28}
    length=${line:79:5}

    #Data Encoded Post
    curl -s \
    --data-urlencode "cart=$cart" \
    --data-urlencode "type=$type" \
    --data-urlencode "title=$title" \
    --data-urlencode "length=$length" \
    -X POST http://my.server.io/metadata/update

fi

完成