swoole版本 4.2.13
粘包问题的产生和解决办法
产生原因
TCP 是流式协议没有消息边界,客户端向服务器端发送一次数据,可能会被服务器端分成多次收到。客户端向服务器端发送多条数据。服务器端可能一次全部收到。
发送方:发送方需要等缓冲区满才发送出去,造成粘包
接收方:接收方不及时接收缓冲区的包,造成多个包接收
粘包问题展现
客户端代码
<?php //粘包示例 客户端 $client = new Swoole\Client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_SYNC); $client->connect("127.0.0.1",9331); for ($i=1;$i<10;$i++){ $client->send("123456".PHP_EOL); } echo $client->recv(); $client->close();
服务端代码
<?php //粘包示例服务端 $server = new Swoole\Server("0.0.0.0",9331,SWOOLE_PROCESS,SWOOLE_SOCK_TCP); $server->set([ 'worker_num'=>4, ]); $server->on("connect",function (swoole_server $server,int $fd){ echo "与客户端{$fd}已建立连接"; }); $server->on("receive",function (swoole_server $server,int $fd,$reactor_id,$data){ $server->send($fd,"服务端已成功接收消息"); echo "服务端收到客户端消息{$data}".PHP_EOL; }); $server->on("close",function (swoole_server $server,int $fd){ echo "Client {$fd} Close".PHP_EOL; }); $server->start();
启动客户端、启动服务端
[root@localhost bky]# php nb_server.php 与客户端1已建立连接服务端收到客户端消息123456 123456 123456 123456 123456 123456 123456 123456 123456 Client 1 Close
我们发现,分9次发送的消息,在服务端只接收到一次数据。
解决办法
1、
$server->set([ 'worker_num' => 4, //worker process num 'open_eof_check'=>true,//打开EOF检测 'package_eof'=>PHP_EOL,//设置EOF 'open_eof_split'=>true,//开启自动拆分 ]);
我们更改server端的代码,加入相关设置项,再次启动server和client
[root@localhost bky]# php nb_server.php 与客户端1已建立连接服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 服务端收到客户端消息123456 Client 1 Close
可以发现粘包问题已解决
未完待续