Php async udp stream socket lost packets

  asynchronous, php, sockets, stream, udp

I have two scripts : server.php and client.php, first sets a php stream socket udp server, the second sends a 20M payload to the server ..

I’ve got lost packets in the process, almost 80% of them ..
Never reached to the #points1,2,3
The more I split the sending in client.php via $mtu, the more I receive in server, but it also consumes lots of time.. And send the data in various "connections" ( sometimes receives nothing in $buf )
And I don’t get any response in client.php for confirming the sent is okay ..

Goal of this script is to setup one day a quick udp async server in order to collect logs from various machines .. For now a standard Nginx+PhpFpm with plain Http behaves better and quicker than this .. I even tried with tcp, but get stuck on connection refused (111)

Thanks you all for any potential clue, notice, enlightment 😉


<?php #php server.php
function ec($x){return;echo $x;}
ini_set('memory_limit',-1);$maxLength=8192;#
$adr='udp://0.0.0.0:1983';$fl=pow(2,13);
$_w=$_e=NULL;
$nbr=$killed=$cumulated=$sleep=0;$waitNextConnectionEach=1;
$socket = stream_socket_server($adr,$errno,$errstr,STREAM_SERVER_BIND);
stream_set_blocking($socket, 0);
$read=$connections=[$socket];
$msg=[];

if (!$socket) {
    echo "Error : no socket : $errstr ($errno)<br />n";
} else {
    echo "nServer listening $adr .. $fl";
    $tot='';$j=0;
    while (!$killed) {
        $read = $connections;
        $mod_fd = stream_select($read, $_w, $_e, $waitNextConnectionEach);
        if($_w){print_r($_w);}if($_e){print_r($_e);}#never happened
        if ($mod_fd === FALSE) {break;}#if error
        if ($mod_fd === 0) {#no pending incoming connection, write last message
            if($msg){
                echo"nnTook:".round(($last-$time)*1000).'ms';
                stream_socket_sendto($socket,'write something');
                fwrite($socket,'write something else');
                $time=null;#set new time for next collection
                foreach($msg as $peer=>$data){$p=preg_replace('~[^a-z0-9.-_]~is','',$peer);
                    $f=date('YmdHis').'-'.$p.'.msg';file_put_contents($f,$data);}
            }
            $cumulated=0;
        }
        for ($i = 0; $i < $mod_fd; ++$i) {
            if ($read[$i] === $socket) {
                if(0){#wont work ..
                    while ($conn = stream_socket_accept($read[$i],30,$peer)) {
                        socket_set_blocking($conn, 0);
                        $connections[] = $conn;
                        echo "new client! id: " . array_key_last($connections) . " peername{$peername}n";
                    }
                }
                #=> 1 "single sent triggers several connections"
                echo "n - $mod_fd pending for $nbr th connection ";
                if(!$time)$time=microtime(1);
                while($buf=stream_socket_recvfrom($socket,$fl,0,$peer)){
                    $len=strlen($buf);$cumulated+=$len;$msg[$peer].=$buf;
                    echo "n$peer,line:$j;len:".strlen($buf).','.$cumulatedulated;
                    $j++;
                }
                $last=microtime(1);
            } else {#POINT1---never happened even while query 999 connections using php client.php &

            }
        }
    }
}
?>

<?php #php client.php
$adr='udp://127.0.0.1:1983';$i=0;$mtu=4096;$split=round($mtu*0.5);
$put='';
while($tot<20000000){
    $re="n".$i.'-';$i++;
    $put.=$re.str_repeat('a',$mtu-strlen($re));
    $tot+=$mtu;
}

$fp=stream_socket_client($adr, $errno, $errstr, 30);
if (!$fp) {echo "$errstr ($errno)<br />n";} else {
    $len=strlen($put);$nb=$sent=$over=0;
    while(!$over && $sent<$len){
        $nb++;
        $sentNow=fwrite($fp,substr($put,$sent,$split),$split);
        $sent+=$sentNow;
        if(!$sentNow)$over=1;
    }
    #POINT2 => never gets a response
    $buf=stream_socket_recvfrom($fp, 1024, 0, $peer);
    print_r(compact('nb','sent'));
}
?>

Source: Ask PHP

LEAVE A COMMENT