|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2021-07-28 00:48 UTC] odarcan at gmail dot com
Description:
------------
a simple tcp socket listen loop (1listen.php) that sends 12mb data to whoever connects to port 1234 and writes "cmd"
the receiver script connects to localhost:1234 and writes "cmd" and counts the number of bytes received (2receive.php) receives different amount and rarely, but sometimes the correct amount.
1listen.php
<?php
ini_set('error_reporting', E_ALL ^ E_NOTICE);
ini_set('display_errors', 1);
set_time_limit (0);
$address = '0.0.0.0';
$port = 1234;
function o($t,$x="\n"){ //just placebo for echo
echo "s_l: $t$x";
}
while (1){
$linger = array ('l_linger' => 0, 'l_onoff' => 1);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_LINGER, $linger);
$r=socket_bind($socket, $address, $port);
if ($r==false){
var_dump($socket);
o("Could not bind to address: $address $port");
o("sleeping...");
unset($socket);
sleep(1);
continue;
}
$r=socket_listen($socket);
if ($r==false){
o("could not listen to socket on $port");
sleep(5);
continue;
}
o("Listening on $address:$port...");
$c=0;
while (true){
$msgsocket = socket_accept($socket);
socket_set_option($msgsocket, SOL_SOCKET, SO_LINGER, $linger);
$received= socket_read($msgsocket,2048,PHP_BINARY_READ);
if($received ===false){
echo "socket read error: ".socket_strerror(socket_last_error($msgsock)) . "\n";
sleep(4);
continue 2;
}
o("-----------------------");
if ($received !==""){
$string=trim($received);
echo "received: [$string]\n";
$cmd=explode(" ",$string);
if ($cmd[0]=="cmd"){
$domain=$cmd[1];
$md5=$cmd[2];
$arr=[];
$n=1;
for($a=0;$a<1000;$a++){
for($b=0;$b<1000;$b++){
$arr[$a][$b]=$a;//generate data to send
}
}
$r2=serialize($arr);
$l1=strlen($r2);
$l2=socket_write($msgsocket,$r2);
if ($l2<$l1){
o("incomplete transfer");
}
o("wrote $l1 / $l2 bytes");
if ($l2===false){
o("error failure");
}
}
}
socket_close($msgsocket);
}
socket_close($socket);
}
shutdown();
?>
2receive.php
<?php
$m="cmd";
$r=sendclosetcp("localhost",1234,$m);
echo strlen($r);
echo "\n";
function o($t,$x="\n"){
global $domain;
$computer="";
echo $computer." $t$x";
}
function sendclosetcp($ip,$port,$msg){
$clnt_sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$r=socket_connect($clnt_sock, $ip, $port);
if ($r==false){
o("could not connect to $ip $port");
return "";
}
socket_write($clnt_sock,$msg);
$ret="";
while(1){
$buf=@socket_read($clnt_sock, 10000, PHP_BINARY_READ);
if (strlen($buf)<19)
var_dump($buf);
$ret.=$buf;
$e=socket_last_error($clnt_sock);
if ($buf===false){
o("1 remote host closed the connection $e");
break;
}
if ($buf==false){
o("2 remote host closed the connection $e");
break;
}
if ($buf==""){
o("3 remote host closed the connection $e");
break;
}
if ($buf===""){
o("4 remote host closed the connection $e");
break;
}
}
o("received ".strlen($ret)." bytes");
return $ret;
}
?>
Test script:
---------------
run 1listen.php in one terminal window
and 2receive.php in another
each time you run 2receive.php it receives different amount of bytes before the connection is closed, I have tried on more than one computer
Expected result:
----------------
"sent x bytes"
and
"received x bytes"
should be the same number
seemingly randomly for files over a few mbs, the received amount varies and data transfers are incomplete
Actual result:
--------------
1listen.php: wrote 11794899 / 11794899 bytes
for example
2receive.php:
received 11053512 bytes
received 8039296 bytes
received 9108280 bytes
etc.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Nov 20 21:00:01 2025 UTC |
you can add if (unserialize($r)===false){ echo "incomplete data transfer\n"; } to the line under $r=sendclosetcp(.... to warn that the data sent is incomplete.solution is this apparently socket_write causes buffer overrun when the msg is too big, so send it in chunks instead $l1=strlen($msg); $totaltransferred=0; $bsize=10000; for ($a=0;$a<$l1;$a+=$bsize){ $part=substr($msg,$a,$bsize); $l2=socket_write($msgsocket,$part,strlen($part)); $totaltransferred+=$l2; } if ($totaltransferred<$l1){ o("incomplete transfer"); }