开发者

PHP socket_read() only gets the first byte of the stream

I'm getting a very weird behavior when using socket_read() in linux.

I'm using socke开发者_运维知识库t_read with a 2048 buffer limit.

While on my windows system it gets the whole response, on my Linux server it just gets the first byte of the response.

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!socket_connect($sock, 'my-server.dyndns.org', 8888)) {
   die('no connect');
}

$req = 'request';
socket_write($sock, $req);

if (false !== ($buf = socket_read($sock, 2048)) {
    echo $buf; // This only contains the first byte of the response.
}

socket_close($sock);

If I call socket_read() again it gets the rest of the string:

// This works: 

while((false !== ($buf = socket_read($sock, 2048)))) {
    echo "Read ".strlen($buf)." bytes from socket_read().\n";
    if ($buf == "") break;
    $b .= $buf;
    sleep(1);
}

/* Output: 
 *
 * Read 1 bytes from socket_read().
 * Read 307 bytes from socket_read().
 * Read 0 bytes from socket_read().
 * Done.
 */ 

If I wait for 2 seconds before calling socket_read(), I also get a valid response:

// This also works:

sleep(2);
if (false !== ($buf = socket_read($sock, 2048)) {
    echo $buf; // all 308 bytes are read correctly.
}

Shouldn't socket_read() wait for the buffer to get full, or for the end of string?

What am I doing wrong?


It's known that the network stack on linux is way better (faster) than on windows (that's subjective, let's just say: it behaves differently). On the other hand that means, that your code needs to deal with the differences, too.

Sockets are not real-time but asynchronous. So if you write something to a socket you can not expect that you already can read on it. You need to give the remote daemon some time to actually response to your write.

Only if the remote side did actually wrote something to your socket and the network has transferred that data, you can read it.


You need to quantify "the whole response".

If by "the whole response", you mean, all the data that is written to the socket before it is closed, then you need to use a loop getting more data. recv is not guaranteed to send all the data in a single chunk.

I would strongly recommend that you don't use the ancient socket_ functions, but instead the fsockopen and fread instead.


In the manual of php says that the read ends with a \r \n if the type is set to PHP_NORMAL_READ string socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )

Maybe in your case must be socket_read($sock, 2048,PHP_NORMAL_READ) to indicate that it must stop reading at a \r\n

Otherwise you can try with a normal fsockopen, and fread instead... it usually goes fine on linux.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜