网络通信过程中,可能会出现分包和合包的情况。具体情况如https://wiki.swoole.com/wiki/page/484.html文档所讲的。这里测试了下固定包头的协议。示例代码如下
1.解包封装的方法
communicationPack.php
<?php //对数据信息封装 function packData($sendData,$packModel){ return pack($packModel, strlen($sendData)).$sendData; } //解包 function unpackData($rcvData,$packModel){ $length = $packModel=='N'?4:2; return substr($rcvData,$length); }
2.服务端 tcpServer.php
<?php require_once 'communicationPack.php'; $packModel = 'N'; //创建Server对象,监听 127.0.0.1:9501端口 $serv = new swoole_server("127.0.0.1", 9501); $serv->set(array( 'open_length_check' => true, 'package_max_length' => 2000000, 'package_length_type' => $packModel, //see php pack() 'package_length_offset' => 0, 'package_body_offset' => $packModel=='N'?4:2, )); //监听连接进入事件 $serv->on('connect', function ($serv, $fd) { echo "Client: Connect.\n"; }); //监听数据接收事件 $serv->on('receive', function ($serv, $fd, $from_id, $data) use($packModel){ echo "#{$serv->worker_id}>> received length=" . strlen($data) ."data=".$data. "}\n"; $data = unpackData($data,$packModel); $returnStr = "Server: ".$data; $serv->send($fd, packData($returnStr,$packModel)); }); //监听连接关闭事件 $serv->on('close', function ($serv, $fd) { echo "Client: Close.\n"; }); //启动服务器 $serv->start();
启动服务端
3 客户端 tcpClient.php
<?php require_once 'communicationPack.php'; $packModel = 'N'; $client = new swoole_client(SWOOLE_SOCK_TCP); $client->set(array( 'open_length_check' => true, 'package_length_type' => $packModel, 'package_length_offset' => 0, //第N个字节是包长度的值 'package_body_offset' => $packModel=='N'?4:2, //第几个字节开始计算长度 'package_max_length' => 2000000, //协议最大长度 )); //连接到服务器 if (!$client->connect('127.0.0.1', 9501, 0.5)) { die("connect failed."); } //向服务器发送数据 //数据协议 $sendData = "test123"; $sendData = packData($sendData,$packModel); if (!$client->send($sendData)) { die("send failed."); } //从服务器接收数据 $data = $client->recv(); if (!$data) { die("recv failed."); } echo unpackData($data,$packModel); //关闭连接 $client->close();
然后启动客户端
服务端会打印
pack N是将数据转成了无符号32位的数字,这个刚好长度是4个字节,所以设定
package_body_offset=4