swoole 自定义协议解决粘包

字节序,不通的设备系统中按照特定的方式读取数据

 

思路:客户端 定义包头 前几个字节 描述包体长度 pack。服务端按此规则upack

<?php
$client = new swoole_client(SWOOLE_SOCK_TCP);
$client->connect('127.0.0.1',9800);
//一次性发送多条,会粘一起
//for($i=1;$i<=10;$i++){
////解决办法,约定一个分隔符,弊端传输数据中不能包含分隔符
//$client->send("123456\r\n");
//}
//一次发送大量数据,拆分小数据
$body = json_encode(str_repeat('a',1*1024*1024));

$data = pack("N",strlen($body)).$body;
$client->send($data);
//echo $client->recv();
<?php
/**
 * Created by PhpStorm.
 * User: zhangheg
 * Date: 2019/3/23
 * Time: 17:45
 */
//创建Server对象,监听 0.0.0.0:9501端口
$serv = new swoole_server("0.0.0.0", 9800);

$serv->set([
    'worker_num' => 1, //设置进程
    //'heartbeat_check_interval'=>3, //心跳间隔时间
    //'heartbeat_idle_time' => 15, //允许空闲时间 心跳的两倍,容错,允许一次丢包
    'open_length_check' => true,
    'package_max_length' => 1024*1024*2, //允许最大
    'package_length_type' => 'N', //设置包头的长度
    'package_length_offset' => 0,
    'package_body_offset' => 4, //包体从第几个字节开始计算
]);


//监听连接进入事件,有客户端连接进来的时候会触发
$serv->on('connect',array(new A(),'connect'));


//监听数据接收事件,server接收到客户端的数据后,worker进程内触发该回调
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
    //var_dump("消息过来:".strlen($data));
    //解包 并截取数据包 截取的长度就是包头长度
   $info = unpack("N",$data);
    var_dump('长度:',$info);
    var_dump(substr($data,4));
    //$serv->send($fd, "服务器给你发送消息了: ".$data);
});
}); //监听连接关闭事件,客服端关闭,或者服务器主动关闭 $serv->on('close', function ($serv, $fd) { echo "编号为{$fd}的客户端已经关闭.".PHP_EOL; }); //启动服务器 $serv->start(); class A{ public function connect($serv, $fd){ var_dump('classa连接'); echo "有新的客户端连接,连接标识为$fd" . PHP_EOL; } }

注意:如果没有按照固定的格式打包方式打包 或者数据包过大 都会报

[2019-04-07 12:56:29 #7631.0] WARNING swProtocol_recv_check_length: package is too big, [2019-04-07 12:56:29 #7631.0] WARNING swProtocol_recv_check_length: package is too big,

每个socket被创建后都会产生两个 缓冲区,输入、输出缓冲区。一旦写入到缓冲区函数就会返回。不管是否发送到目标机器,也不管何时发送,这些都是tcp协议负责的

注意:回复机制。不要send后立即close

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注