您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
workerman自定义协议-xml数据包-包长与包首部
发布时间:2021-11-28 14:58:07编辑:雪饮阅读()
协议定义
首部固定10个字节长度用来保存整个数据包长度,位数不够补0
数据格式为xml
数据包样本
0000000121<?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
其中0000000121代表整个数据包长度,后面紧跟xml数据格式的包体内容
意思就是说这个xml用户本来要发送的只是:
<?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
但是这样服务端无法获知包长度,就和服务端约定协商,包的前10个字符表示包长,不够10个字符就用前导0实现。
这里这个xml长度是121个字符,121才3位不足10位那么用前导0后就是:
0000000121
然后封装后给服务端真正发送的数据就是:
0000000121<?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
这个了。
协议实现:
XmlProtocol.php:
<?php
namespace Workerman\Protocols;
class XmlProtocol
{
public static function input($recv_buffer)
{
if(strlen($recv_buffer) < 10)
{
// 不够10字节,返回0继续等待数据
return 0;
}
// 返回包长,包长包含 头部数据长度+包体长度
//
/*substr($recv_buffer, 0, 10)获取首部字符串即:
0000000121<?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
中的0000000121
然后用base_convert将0000000121这个从10进制转换到10进制就是121
*
* */
$total_len = base_convert(substr($recv_buffer, 0, 10), 10, 10);
return $total_len;
}
public static function decode($recv_buffer)
{
// 请求包体
$body = substr($recv_buffer, 10);
return simplexml_load_string($body);
}
public static function encode($xml_string)
{
// 包体+包头的长度
$total_length = strlen($xml_string)+10;
// 长度部分凑足10字节,位数不够补0
$total_length_str = str_pad($total_length, 10, '0', STR_PAD_LEFT);
// 返回数据
return $total_length_str . $xml_string;
}
}
协议服务启动脚本:start.php:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$json_worker = new Worker('XmlProtocol://0.0.0.0:1234');
$json_worker->onMessage = function(TcpConnection $connection, $data) {
// $data就是客户端传来的数据
var_dump($data);
$xml=<<<STRING_XML
<?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
STRING_XML;
$connection->send($xml);
};
Worker::runAll();
协议测试:
[root@localhost ~]# telnet 127.0.0.1 1234
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
0000000121<?xml version="1.0" encoding="ISO-8859-1"?>
<request><module>user</module><action>getInfo</action>
</request>
0000000137 <?xml version="1.0" encoding="ISO-8859-1"?>
<request>
<module>user</module>
<action>getInfo</action>
</request>
协议服务端响应:
[root@localhost workerman]# php -c /usr/local/php734/lib/php/php.ini start.php start
Workerman[start.php] start in DEBUG mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version:4.0.22 PHP version:7.3.4
--------------------------------------------- WORKERS ----------------------------------------------
proto user worker listen processes status
tcp root none xmlProtocol://0.0.0.0:1234 1 [OK]
----------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
object(SimpleXMLElement)#15 (2) {
["module"]=>
string(4) "user"
["action"]=>
string(7) "getInfo"
}
注意:xml中换行也会增加字符数。
关键字词:workerman,xml,包长,包首部