Doc->Bug #81304 [Nab]: simple socket listen and receive scripts transfer incomplete data
| From: | requinix@php.net | Date: | Thu, 29 Jul 2021 01:22:46 +0000 |
| Subject: | Doc->Bug #81304 [Nab]: simple socket listen and receive scripts transfer incomplete data | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-235449@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=81304&edit=1
ID: 81304
Updated by: requinix@php.net
Reported by: odarcan at gmail dot com
Summary: simple socket listen and receive scripts transfer
incomplete data
Status: Not a bug
-Type: Documentation Problem
+Type: Bug
Package: Sockets related
Operating System: linux
PHP Version: 7.4.21
Block user comment: N
Private report: N
New Comment:
Please note that the term "buffer overrun" means something very different from what you
meant.
https://www.php.net/manual/en/function.socket-write.php
> Note:
> socket_write() does not necessarily write all bytes from the given buffer.
> It's valid that, depending on the network buffers etc., only a certain amount
> of data, even one byte, is written though your buffer is greater. You have to
> watch out so you don't unintentionally forget to transmit the rest of your
> data.
Previous Comments:
------------------------------------------------------------------------
[2021-07-29 00:58:35] odarcan at gmail dot com
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");
}
------------------------------------------------------------------------
[2021-07-28 01:14:35] requinix@php.net
Sorry, but your problem does not imply a bug in PHP itself. For a
list of more appropriate places to ask for help using PHP, please
visit http://www.php.net/support.php as this bug system
is not the
appropriate forum for asking support questions. Due to the volume
of reports we can not explain in detail here why your report is not
a bug. The support channels will be able to provide an explanation
for you.
Thank you for your interest in PHP.
------------------------------------------------------------------------
[2021-07-28 01:00:53] odarcan at gmail dot com
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.
------------------------------------------------------------------------
[2021-07-28 00:48:54] 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.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=81304&edit=1