0%

swoole 粘包问题

先来讲解,为什么会产生粘包问题呢,网上炒了一段,如果想要仔细了解的同学可以去搜寻一下对应的资料

  • 当应用层协议使用 TCP 协议传输数据时,TCP 协议可能会将应用层发送的数据分成多个包依次发送,而数据的接收方收到的数据段可能有多个『应用层数据包』组成,所以当应用层从 TCP 缓冲区中读取数据时发现粘连的数据包时,需要对收到的数据进行拆分。

1.话不多说上代码,服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//创建Server对象,监听 127.0.0.1:9501 端口
$server = new Swoole\Server('127.0.0.1', 9501);
$server->set([
'open_length_check' => true,//打开包检测
'package_max_length' => 1 * 1024 * 1024, //1兆
'package_length_type' => 'n', //小n 2个字节,大N 4个字节
'package_length_offset' => 0,//包头从第几位开始截取
'package_body_offset' => 2,//包头到几位结束
]);


//监听连接进入事件
$server->on('Connect', function ($server, $fd) {
echo "Client: Connect.\n";
});

//监听数据接收事件
$server->on('Receive', function ($server, $fd, $from_id, $data) {
echo '接收到数据:'.$data.PHP_EOL;
$server->send($fd, "Server: " . $data);
});

//监听连接关闭事件
$server->on('Close', function ($server, $fd) {
echo "Client: Close.\n";
});

//启动服务器
$server->start();

2.客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

$client = new Swoole\Client(SWOOLE_SOCK_TCP );

if (!$client->connect('127.0.0.1', 9501, -1)) {
exit("connect failed. Error: {$client->errCode}\n");
}

//粘包
for($i=0; $i<10; $i++){
$str = 'hello';//要发送的内容
$len = pack('n',strlen($str));//把长度转换二进制,n表示2个字节长度
$send = $len.$str;//拼接
var_dump($send);
$client->send($send);//发送

}

$client->recv();

3.执行效果(服务端)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost 03]# php xintiao_tcp_server.php 
Client: Connect.
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
接收到数据:hello
Client: Close.

3.执行效果(客户端)

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost 03]# php xintiao_tcp_client.php 
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"
string(7) "hello"