您当前的位置: 首页 > 慢生活 > 程序人生 网站首页程序人生
workerman自定义协议-jsonl数据包(首部无符号int四字节)及php原生telnet客户端实现
发布时间:2021-11-28 16:38:33编辑:雪饮阅读()
协议定义
首部4字节网络字节序unsigned int,标记整个包的长度
数据部分为Json字符串
数据包样本
****{"type":"message","content":"hello all"}
其中首部四字节*号代表一个网络字节序的unsigned int数据,为不可见字符,紧接着是Json的数据格式的包体数据
协议实现
JsonInt.php:
<?php
namespace Workerman\Protocols;
class JsonInt
{
public static function input($recv_buffer)
{
// 接收到的数据还不够4字节,无法得知包的长度,返回0继续等待数据
if(strlen($recv_buffer)<4)
{
return 0;
}
// 利用unpack函数将首部4字节转换成数字,首部4字节即为整个数据包长度
$unpack_data = unpack('Ntotal_length', $recv_buffer);
return $unpack_data['total_length'];
}
public static function decode($recv_buffer)
{
// 去掉首部4字节,得到包体Json数据
$body_json_str = substr($recv_buffer, 4);
// json解码
return json_decode($body_json_str, true);
}
public static function encode($data)
{
// Json编码得到包体
$body_json_str = json_encode($data);
// 计算整个包的长度,首部4字节+包体字节数
$total_length = 4 + strlen($body_json_str);
// 返回打包的数据
return pack('N',$total_length) . $body_json_str;
}
}
协议应用入口脚本start.php:
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$json_worker = new Worker('JsonInt://0.0.0.0:1234');
$json_worker->onMessage = function(TcpConnection $connection, $data) {
// $data就是客户端传来的数据
var_dump($data);
$response["response"]=$data;
$connection->send($response);
};
Worker::runAll();
再实现一个简易telnet客户端,用php实现,因为这里首部4字节出现的*号是由二进制实现的,用linux的telnet暂时我这里不晓得如何输入(直觉应该是没有该录入功能),telnet.php:
<?php
function encode($data)
{
// Json编码得到包体
$body_json_str = json_encode($data);
// 计算整个包的长度,首部4字节+包体字节数
$total_length = 4 + strlen($body_json_str);
// 返回打包的数据
return pack('N',$total_length) . $body_json_str;
}
// Create the socket and connect
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$connection = socket_connect($socket, "127.0.0.1", 1234);
//读取
/*
while ($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) {
if ($buffer == "NO DATA")
{
echo ("< p>NO DATA </p >");
break;
}
else
{
// Do something with the data in the buffer
echo ("< p>Buffer Data: ". $buffer . "</p >");
}
}
*/
//echo ("< p>Writing to Socket </p >");
// Write some test data to our socket
$json=encode(["name"=>"gjf","name2"=>"gjp"]);
if (!socket_write($socket, $json."\r\n"))
{
echo ("< p>Write failed </p >");
}
// Read any response from the socket
$buffer="";
$body_json_str="";
while ($buffer.= socket_read($socket, 1024, PHP_BINARY_READ )) {
/*
echo ("< p>Data sent was: SOME DATA Response was:" . $buffer . "</p > ");
*/
if(strlen($buffer)<4)
{
}
else{
$body_json_str = substr($buffer, 4);
break;
}
}
echo "body_json_str:".$body_json_str."\r\n";
然后接下来就是测试了:
json数据包协议服务端:
[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 jsonInt://0.0.0.0:1234 1 [OK]
------------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.
array(2) {
["name"]=>
string(3) "gjf"
["name2"]=>
string(3) "gjp"
}
telnet客户端:
[root@localhost ~]# php -c /usr/local/php734/lib/php/php.ini /workerman/telnet.php
body_json_str:{"response":{"name":"gjf","name2":"gjp"}}
关键字词:workerman,json,int,无符号,php,telnet