Swoole 产生 粘包 和 解决 粘包 得问题

Swoole 产生 粘包 和 解决 粘包 得问题

粘包是什么?如何产生?

粘包是什么?
 白话说:粘包就是A端分多次发送的数据 到达B端时数据接受到的是一个数据。
 
 当然不是数据丢失了,而是A端的数据合并在了一个包中然后发送到了B端。
粘包是如何产生的呢?
    大概概念:因为TCP每次发送数据是比叫严谨的一个过程,要经三次握手然后发送数据然后还要四次挥手等一系列
操作,非常消耗资源,然后就存在了  拥塞控制 的技术,而 拥塞控制 就是粘包的根本原因。

	拥塞控制 白话说:就是特定时间内发送一次数据,这样会把我们发送的多个数据缓冲到一个包中。
	
	举例:坐公交:公交车的发车时间是又时间点的,并不是来一个人就发一辆车。车就是代表发送总数据。而人就代表
发送一次的数据。

粘包的解决在swoole中。

  1. 添加分隔符。(这中办法会存在一定的问题。如果数据中存在分隔符呢?又如果请求太多数据挺大的,岂不是很消耗资源。所以淘汰。)

  2. 我要说的正是添加包头这种写法。

    这其中需要用到一对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);

注:此文章只是学习总结,如有不对,还望海纳并指点。。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值