Swoole 学习笔记 03

 

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

可以发现粘包问题已解决

 

未完待续

 

上一篇:swoole| swoole 协程初体验


下一篇:呕心搜集总结的15个“swoole”常见问题(一)