视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
swoole json不完整怎么办
2020-11-03 13:38:59 责编:小采
文档


swoole json不完整怎么办?

swoole客户端与服务端收发数据完整性问题解决

一、下面这个实例,启动swoole服务后,监听9501端口,接收从客户端发来的数据,原样返回。

class Server
{
 private $serv;
 public function __construct() {
 $this->serv = new swoole_server("127.0.0.1", 9501);
 $this->serv->set(array(
 'worker_num' => 4, //一般设置为服务器CPU数的1-4倍
 'daemonize' => 1, //以守护进程执行
 'max_request' => 2000,
 'dispatch_mode' => 2,//进程数据包分配模式 1平均分配,2按FD取摸固定分配,3抢占式分配
 'task_worker_num' => 8, //task进程的数量
 "task_ipc_mode " => 3 , //使用消息队列通信,并设置为争抢模式
 "log_file" => "./log/taskqueueu.log" ,//日志
 ));
 $this->serv->on('Receive', array($this,'onReceive'));//接收到数据时回调此函数
 $this->serv->start();
 }
 public function onReceive(swoole_server $serv, $fd, $from_id, $data ) {
 $serv->send($fd, $data);
 usleep(500); //不加延时的话,经常两条数据被合并成一条返回了。
 $serv->close($fd);
 } 
 public function onClose(swoole_server $serv, $fd) {
 $serv->send($fd, 'CLOSED');
 } 
}

直接new Server启动服务端。

二、启动swoole客户端,向服务端发数据,并接收返回。

$client = new swoole_client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, -1))
{
 exit("connect failed. Error: {$client->errCode}
");
}
$data=[
 'type'=>1, 
 'data'=>array(
 'PlatformCode'=>'...........很长的数据.',
 )
 ];
$sender=$client->send(json_encode($data)."

");
while($result = $client->recv()){
 if($result=='CLOSED'){
 echo "任务结束。byebye~
";
 break;
 }else{
 echo $result;
 }
}
$client->close();

当发送比较大的数据包时,会发现接收到的json包是不完整的,可以使用EOF协议处理的方式来解决,比如在服务端设置:

 $serv->set(
 array('open_eof_split' => TRUE, 'package_eof' => "

")
 );

这样,' '就成为EOF协议结束符。

发送数据包时,在包结尾添加上' ',接口数据时遇到这个字符就认为数据接收完毕,如此就保证的数据的完整性。

注:数据包中不能出现' '字符,否则会出现分包错误。

Swoole的Server和异步Client都是在onReceive回调函数中处理数据包,当设置了协议处理后,只有收到一个完整数据包时才会触发onReceive事件。

另外一种方式,也可以预先设定好要发送的包的长度,如:

$server->set(array(
 'open_length_check' => true,
 'package_max_length' => 81920,
 'package_length_type' => 'n', //see php pack()
 'package_length_offset' => 0,
 'package_body_offset' => 2,
));

可以固定包的长度来确保数据的完整性,官方注释如下:

固定包头的协议非常通用,在BAT的服务器程序中经常能看到。这种协议的特点是一个数据包总是由包头+包体2部分组成。包头由一个字段指定了包体或整个包的长度,长度一般是使用2字节/4字节整数来表示。服务器收到包头后,可以根据长度值来精确控制需要再接收多少数据就时完整的数据包。Swoole的配置可以很好的支持这种协议,可以灵活地设置4项参数应对所有情况。

Swoole的Server和异步Client都是在onReceive回调函数中处理数据包,当设置了协议处理后,只有收到一个完整数据包时才会触发onReceive事件。同步客户端在设置了协议处理后,调用 $client->recv() 不再需要传入长度,recv函数在收到完整数据包或发生错误后返回。

下载本文
显示全文
专题