workerman当然是完整的没有粘包问题,但是我使用自己的程序接收workerman发送过来的信息时出现了这个问题,即从workerman发送的一条一条的信息变成了一整条的了,这个有一个通用的解决方案吗,我使用的是文本传递协议。。。求解
使用接收程序如下:
while ( $buf = stream_socket_recvfrom ( $new_conn, 65535 ) ) { $all_buffer .= $buf; if($buf === "\n") { break; } return $all_buffer; }
接收一个一个字符接收是为了检查边界 结果很明显会有粘包的现象,因为一下子读那么多,而且接收的数据实际是上多条的, 在这里判断边界其实是没有意义的,那么怎么办呢:
while ( $buf = stream_socket_recvfrom ( $new_conn, 1 ) ) { $all_buffer .= $buf; if($buf == "\n") { break; } return $all_buffer; }
我就一个一个的接收,这总行了吧,结果又是没什么: 没有了粘包问题,但接收的数据把我的整条信息拆开了,这又不是我想要的,为什么会在接收到 "\n"之前我的循环就跳出了呢? 这得考虑socket数据传输的特性了,这的规则是我们接收和发送定义的,而它自己的规则对我们来说没有实际的处理意义,即stream_socket_recvfrom返回来的可能为空。没能等到"\n"就已经跳出了。
最后walkor提供了以下方法:
$all_buffer = ''; while(1) { $buf = stream_socket_recvfrom ( $new_conn, 1 ); if(empty($buf)) { if(feof($buf)) { break; } continue; } $all_buffer .= $buf; if($buf == "\n") { break; } } return $all_buffer;
问题解决。
处理方法类似,根据协议判断请求边界。 例如协议是 json+回车
客户端应该类似这样读
$client = stream_socket_client('tcp://ip:port'); $all_buffer = ''; while(1) { // 每次读一个字节,因为每个字节都有可能是代表数据的结束的回车字符 $buf = stream_socket_recvfrom($client, 1); // stream_socket_recvfrom 可能返回空,比如$client是非阻塞的,或者被信号打断、断开、超时等 if(empty($buf) && $buf != '0') { // 链接断开就跳出 if(feof($buf)) { break; } // 继续 continue; } // 拼接数据 $all_buffer .= $buf; // 是请求边界就跳出 if($buf == "\n") { break; } }
当然上面的协议简单,但是由于是一个字节一个字节的读,对性能有一点点的损耗
如果对性能要求非常非常苛刻,可以采用 类似 包长+包体 的协议传输
额,jorry已经回答了
看了一下代码。是不是
if(empty($buf)) { // 链接断开就跳出 if(feof($buf)) { break; } // 继续 continue; }
这样就把字符中的空格给抹掉了?
应该不会抹掉空格,但是会抹掉 '0' 字符,得加个判断
if(empty($buf) && $buf != '0') { // 链接断开就跳出 if(feof($buf)) { break; } // 继续 continue; }
使用接收程序如下:
接收一个一个字符接收是为了检查边界
结果很明显会有粘包的现象,因为一下子读那么多,而且接收的数据实际是上多条的,
在这里判断边界其实是没有意义的,那么怎么办呢:
我就一个一个的接收,这总行了吧,结果又是没什么:
没有了粘包问题,但接收的数据把我的整条信息拆开了,这又不是我想要的,为什么会在接收到 "\n"之前我的循环就跳出了呢?
这得考虑socket数据传输的特性了,这的规则是我们接收和发送定义的,而它自己的规则对我们来说没有实际的处理意义,即stream_socket_recvfrom返回来的可能为空。没能等到"\n"就已经跳出了。
最后walkor提供了以下方法:
问题解决。
处理方法类似,根据协议判断请求边界。
例如协议是 json+回车
客户端应该类似这样读
当然上面的协议简单,但是由于是一个字节一个字节的读,对性能有一点点的损耗
如果对性能要求非常非常苛刻,可以采用 类似 包长+包体 的协议传输
额,jorry已经回答了
看了一下代码。是不是
if(empty($buf))
{
// 链接断开就跳出
if(feof($buf))
{
break;
}
// 继续
continue;
}
这样就把字符中的空格给抹掉了?
应该不会抹掉空格,但是会抹掉 '0' 字符,得加个判断
if(empty($buf) && $buf != '0')
{
// 链接断开就跳出
if(feof($buf))
{
break;
}
// 继续
continue;
}