PHP socket跨机器丢失数据问题
发现socket跨机器访问时,客户端读不到完整数据,下面是简化了一些流程的关键代码
服务端代码
<?php
$uri = 'tcp://0.0.0.0:8522';
$context = stream_context_create([]);
$errno = 0;
$errStr = '';
$server = stream_socket_server($uri, $errno, $errStr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context);
$socket = socket_import_stream($server);
socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);
while ($conn = stream_socket_accept($server, 10000)) {
stream_set_blocking($conn, 0);
$data = [];
$count = 0;
while ($count < 8000) {
$data[] = [
'id' => 'qwertyuiop123456',
'name' => 'abcdef123的撒第五期红地球完活i都会去的',
];
$count++;
}
$data = json_encode($data);
$length = strlen($data);
echo $length . chr(10);
fwrite($conn, $data);
fclose($conn);
}
fclose($server);
客户端
<?php
$uri = 'tcp://0.0.0.0:8522';
$errno = 0;
$errStr = '';
$stream = stream_socket_client($uri, $errno, $errStr, 30, STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT, stream_context_create([]));
$socket = socket_import_stream($stream);
socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1);
socket_set_option($socket, SOL_TCP, TCP_NODELAY, 1);
$read[] = $stream;
$write = $e = [];
$response = '';
while (stream_select($read, $write, $e, 1)) {
$response .= fread($stream, 1040001);
if (strlen($response) >= 1040001) {
break;
}
}
echo $response . chr(10);
echo strlen($response) . chr(10);
这个问题需要服务端访问数据大才能复现,同一台机器上客户端可以收到完整报文,但是不同机器时就收不到了
后来我把服务端的stream_set_blocking
设置为 1,客户端就可以收到完整报文,非阻塞下收不到完整报文,请问是哪里有问题?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
stream_set_blocking
引起的问题。由于非阻塞模式,
fwrite
的数据有可能写入不完整就返回了(阻塞模式不会,一定是写完才返回,写不完就阻塞直到写完),所以客户端收到的数据被截断了。系统的I/O是有速度限制的,比如100KB/s,超过该限制的话需要等待网卡就绪才能写入。
fwrite
一直等待,直到系统底层可写才发送,数据最终也会被完整写入。fwrite
会返回当前写入成功的字节数,如果写入成功的字节数小于你传递的数据长度,则证明可写字节不够,需要调用stream_select
对可写流进行可写状态监听
,然后把剩余的数据进行fwrite