Swoole 产生 粘包 和 解决 粘包 得问题
粘包是什么?如何产生?
粘包是什么?
白话说:粘包就是A端分多次发送的数据 到达B端时数据接受到的是一个数据。
当然不是数据丢失了,而是A端的数据合并在了一个包中然后发送到了B端。
粘包是如何产生的呢?
大概概念:因为TCP每次发送数据是比叫严谨的一个过程,要经三次握手然后发送数据然后还要四次挥手等一系列
操作,非常消耗资源,然后就存在了 拥塞控制 的技术,而 拥塞控制 就是粘包的根本原因。
拥塞控制 白话说:就是特定时间内发送一次数据,这样会把我们发送的多个数据缓冲到一个包中。
举例:坐公交:公交车的发车时间是又时间点的,并不是来一个人就发一辆车。车就是代表发送总数据。而人就代表
发送一次的数据。
粘包的解决在swoole中。
-
添加分隔符。(这中办法会存在一定的问题。如果数据中存在分隔符呢?又如果请求太多数据挺大的,岂不是很消耗资源。所以淘汰。)
-
我要说的正是添加包头这种写法。
这其中需要用到一对
PHP
函数。pack
unpack
下面直接上代码吧。
server端
<?php
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new Swoole\Server("0.0.0.0", 9501);
//设置pack参数
$serv->set([
'open_length_check' => true, // 开启协议解析
'package_length_type' => 'N', // 长度字段的类型
'package_length_offset' => 0, //第几个字节是包长度的值
'package_body_offset' => 4, //第几个字节开始计算长度
'package_max_length' => 81920, //协议最大长度
]);
//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) {
echo "Client: Connect.\n";
});
//监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
$body = substr($data, - unpack('N',$data)[1]);// $body是服务端接收并处理后得到的数据
$packge = pack('N',strlen($body)).$body;// $packge是服务端处理后得到要发送的数据
$serv->send($fd, $packge);//发送到客户端。
echo $body.PHP_EOL;//打印数据
});
//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
client端
<?php
$client = new swoole_client(SWOOLE_SOCK_TCP,SWOOLE_SOCK_ASYNC);
//设置pack参数
$client->set([
'open_length_check' => true, // 开启协议解析
'package_length_type' => 'N', // 长度字段的类型
'package_length_offset' => 0, //第几个字节是包长度的值
'package_body_offset' => 4, //第几个字节开始计算长度
'package_max_length' => 81920, //协议最大长度
]);
//连接到服务器
//注册连接成功回调
$client->on("connect", function($cli) {
for ($i = 0 ; $i<100; $i++){
$data = 'HuiCurry';
$body = pack('N',strlen($data)).$data;// $body是客户端处理后得到发送的数据
$cli->send($body);//发送到服务端
}
});
//注册数据接收回调
$client->on("receive", function($cli, $data){
$body = substr($data, - unpack('N',$data)[1]);//$body是客户端接收并处理后得到的数据
echo "Received: ".$body."\n";//打印数据
});
//注册连接失败回调
$client->on("error", function($cli){
echo "Connect failed\n";
});
//注册连接关闭回调
$client->on("close", function($cli){
echo "Connection close\n";
});
//发起连接
$client->connect('0.0.0.0', 9501, 0.5);
注:此文章只是学习总结,如有不对,还望海纳并指点。。