php如何编写通信协议,定制通讯协议

## 如何定制协议

实际上制定自己的协议是比较简单的事情。简单的协议一般包含两部分:

* 区分数据边界的标识

* 数据格式定义

## 一个例子

### 协议定义

这里假设区分数据边界的标识为换行符"\n"(注意请求数据本身内部不能包含换行符),数据格式为Json,例如下面是一个符合这个规则的请求包。

{"type":"message","content":"hello"}

注意上面的请求数据末尾有一个换行字符(在PHP中用**双引号**字符串"\n"表示),代表一个请求的结束。

### 实现步骤

在WorkerMan中如果要实现上面的协议,假设协议的名字叫JsonNL,所在项目为MyApp,则需要以下步骤

1、协议文件放到项目的Protocols文件夹,例如文件MyApp/Protocols/JsonNL.php

2、实现JsonNL类,以```namespace Protocols;```为命名空间,必须实现三个静态方法分别为 input、encode、decode

注意:workerman会自动调用这三个静态方法,用来实现分包、解包、打包。具体流程参考下面执行流程说明。

### workerman与协议类交互流程

1、假设客户端发送一个数据包给服务端,服务端收到数据(可能是部分数据)后会立刻调用协议的```input```方法,用来检测这包的长度,```input```方法返回长度值```$length```给workerman框架。

2、workerman框架得到这个```$length```值后判断当前数据缓冲区中是否已经接收到```$length```长度的数据,如果没有就会继续等待数据,直到缓冲区中的数据长度不小于```$length```。

4、缓冲区的数据长度足够后,workerman就会从缓冲区截取出```$length```长度的数据(即**分包**),并调用协议的```decode```方法**解包**,解包后的数据为```$data```。

3、解包后workerman将数据```$data```以回调```onMessage($connection, $data)```的形式传递给业务,业务在onMessage里就可以使用```$data```变量得到客户端发来的完整并且已经解包的数据了。

4、当```onMessage```里业务需要通过调用```$connection->send($buffer)```方法给客户端发送数据时,workerman会自动利用协议的```encode```方法将```$buffer```**打包**后再发给客户端。

### 具体实现

**MyApp/Protocols/JsonNL.php的实现**

```php

namespace Protocols;

class JsonNL

{

/**

* 检查包的完整性

* 如果能够得到包长,则返回包的在buffer中的长度,否则返回0继续等待数据

* 如果协议有问题,则可以返回false,当前客户端连接会因此断开

* @param string $buffer

* @return int

*/

public static function input($buffer)

{

// 获得换行字符"\n"位置

$pos = strpos($buffer, "\n");

// 没有换行符,无法得知包长,返回0继续等待数据

if($pos === false)

{

return 0;

}

// 有换行符,返回当前包长(包含换行符)

return $pos+1;

}

/**

* 打包,当向客户端发送数据的时候会自动调用

* @param string $buffer

* @return string

*/

public static function encode($buffer)

{

// json序列化,并加上换行符作为请求结束的标记

return json_encode($buffer)."\n";

}

/**

* 解包,当接收到的数据字节数等于input返回的值(大于0的值)自动调用

* 并传递给onMessage回调函数的$data参数

* @param string $buffer

* @return string

*/

public static function decode($buffer)

{

// 去掉换行,还原成数组

return json_decode(trim($buffer), true);

}

}

```

至此,JsonNL协议实现完毕,可以在MyApp项目中使用,使用方法例如下面

文件:MyApp\start.php

```php

use Workerman\Worker;

require_once '/your/path/Workerman/Autoloader.php'

$json_worker = new Worker('JsonNL://0.0.0.0:1234');

$json_worker->onMessage = function($connection, $data) {

// $data就是客户端传来的数据,数据已经经过JsonNL::decode处理过

echo $data;

// $connection->send的数据会自动调用JsonNL::encode方法打包,然后发往客户端

$connection->send(array('code'=>0, 'msg'=>'ok'));

};

Worker::runAll();

...

```

### 协议接口说明

在WorkerMan中开发的协议类必须实现三个静态方法,input、encode、decode,协议接口说明见Workerman/Protocols/ProtocolInterface.php,定义如下:

```php

namespace Workerman\Protocols;

use \Workerman\Connection\ConnectionInterface;

/**

* Protocol interface

* @author walkor

*/

interface ProtocolInterface

{

/**

* 用于在接收到的recv_buffer中分包

*

* 如果可以在$recv_buffer中得到请求包的长度则返回整个包的长度

* 否则返回0,表示需要更多的数据才能得到当前请求包的长度

* 如果返回false或者负数,则代表错误的请求,则连接会断开

*

* @param ConnectionInterface $connection

* @param string $recv_buffer

* @return int|false

*/

public static function input($recv_buffer, ConnectionInterface $connection);

/**

* 用于请求解包

*

* input返回值大于0,并且WorkerMan收到了足够的数据,则自动调用decode

* 然后触发onMessage回调,并将decode解码后的数据传递给onMessage回调的第二个参数

* 也就是说当收到完整的客户端请求时,会自动调用decode解码,无需业务代码中手动调用

* @param ConnectionInterface $connection

* @param string $recv_buffer

*/

public static function decode($recv_buffer, ConnectionInterface $connection);

/**

* 用于请求打包

*

* 当需要向客户端发送数据即调用$connection->send($data);时

* 会自动把$data用encode打包一次,变成符合协议的数据格式,然后再发送给客户端

* 也就是说发送给客户端的数据会自动encode打包,无需业务代码中手动调用

* @param ConnectionInterface $connection

* @param mixed $data

*/

public static function encode($data, ConnectionInterface $connection);

}

```

## 注意:

Workerman中没有严格要求协议类必须基于ProtocolInterface实现,实际上协议类只要类包含了input、encode、decode三个静态方法即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

今年计划要看的书全部备齐

上个月购买的书《今年计划看的书其中几本》 http://www.cnblogs.com/insus/p/5325513.html 昨天购买的书回来了,今年计划要看的书全部备齐。《MongoDB》,《深入理解Bootstarp》和《ASP.NETSignalR编程实践》…… 转载于:https://www.cnblogs.com/in…

Codevs 2756 树上的路径

2756 树上的路径 时间限制: 3 s    空间限制: 128000 KB    题目等级 : 大师 Master题目描述 Description给出一棵树&#xff0c;求出最小的k&#xff0c;使得&#xff0c;且在树中存在路径P&#xff0c;使得k> S 且 k <E. &#xff08;k为路径P上的边的权值和&a…

图形教程

众所周知&#xff0c;我们可以借助Java库制作游戏&#xff0c;这些库为我们提供制作游戏所需的图形。 因此&#xff0c;今天我将开始一个关于Java图形的非常新的部分。 我之前曾发表过有关如何制作所得税计算器的文章 。 首先要满足一些先决条件&#xff1a; -您应该对Java语法…

文件上传预览

<fieldset><legend>使用readAsDataUrl()方法预览图片</legend><input type"file" name"fileUpload" id"fileUpload" onchange"filePrevImg(this.files);" multiple"true" /><ul id"prevUpl…

c++强制类型转换:dynamic_cast、const_cast 、static_cast、reinterpret_cast

一、介绍 dynamic_cast: 通常在基类和派生类之间转换时使用const_cast: 主要针对const和volatile的转换static_cast: 一般的转换(no run-time check)通常&#xff0c;如果你不知道该用哪个&#xff0c;就用这个。 reinterpret_cast: 用于进行没有任何关联之间的转换&…

K8S Pod Terminating/Unknown故障排查

一、pod异常出现现象 优雅终止周期(Graceful termination period): 当pod被删除时&#xff0c;会进入"Terminating"状态&#xff0c;等待容器优雅关闭。如果容器关闭所需时间超过默认期限(默认30秒)&#xff0c;则pod将保持在"Terminating"状态。 Finalize…

矩阵指数 matlab,矩阵指数 - MATLAB Simulink Example - MathWorks 中国

方法 1&#xff1a;加权平方expmdemo1 是以下著作中算法 11.3.1 的实现&#xff1a;Golub, Gene H. and Charles Van Loan.Matrix Computations, 3rd edition.Baltimore, MD:Johns Hopkins University Press, 1996.% Scale A by power of 2 so that its norm is < 1/2 .[f,e…

向导设计模式

我们都喜欢巫师……。 &#xff08;我的意思是软件向导&#xff09;。 我们总是很高兴跳上那些“下一步”按钮&#xff0c;就像我们在我们的时髦的小鸡上跳舞一样。 因此&#xff0c;今天我们将您心爱的向导带入您的编码经验中。 让我们跳入一个例子。 假设您要设计一个Conserv…

IO(三)字节流练习

public class ByteStreamDemo {/*int available(); 可以取得输入文件的大小&#xff08;字节个数&#xff09;,没有返回0void close(); 关闭输入流abstract int read(); 读取一个字节&#xff0c;并把读…

基于matlab的人脸五官边缘检测方法,人脸边缘检测方法研究与仿真

人脸表情是人类情感的主载体之一,它含有丰富的人体行为信息。通过脸部表情能够表达人微妙的情绪反应以及对应的心理状态[1],人脸表情识别技术随着人们对表情信息的日益重视而受到关注,现已成为人们研究的热点。基于几何特征提取是一个快速、直接、有效的人脸表情识别方法,运用基…

GWT –利弊

我喜欢JavaScript。 随着jQuery和Mootools的出现&#xff0c;我对JavaScript的热爱仅增加了很多倍。 只要有选择&#xff0c;我就可以将上述框架中的任何一个用于我开发的任何Web应用程序。 但是进入服务行业后&#xff0c;我不得不一次次屈服于客户的压力&#xff0c;并在他们…

秦九韶算法matlab实验报告,数值分析上机实验报告.doc

实验报告一题目&#xff1a; (绪论) 非线性方程求解及误差估计摘要&#xff1a;非线性方程的解析解通常很难给出&#xff0c;因此线性方程的数值解法就尤为重要。本实验采用两种常见的求解方法二分法、Newton法和改进的Newton法。可以节省计算机的计算时间&#xff0c;还能减小…

Flex 布局教程:语法篇

网页布局&#xff08;layout&#xff09;是CSS的一个重点应用。 布局的传统解决方案&#xff0c;基于盒状模型&#xff0c;依赖 display属性 position属性 float属性。它对于那些特殊布局非常不方便&#xff0c;比如&#xff0c;垂直居中就不容易实现。 2009年&#xff0c;W3…

练习错误

form:阻止表单提交的方法一&#xff1a;在form标签中给出以下代码&#xff1a; 1 onsubmit "return False" 方法二&#xff1a;设置事件阻止 1 e.preventDefault() js中判断&#xff1a;只要非数字都应该表示为字符串 1 if(Email.indexOf("") -1){ 2 …

JavaFX 2中的PopupMenu

创建弹出菜单 要在JavaFX中创建Popupmenu&#xff0c;可以使用ContextMenu类。 您向其中添加MenuItems&#xff0c;也可以使用SeparatorMenuItem创建可视分隔符。 在下面的示例中&#xff0c;我选择子类ContextMenu并将MenuItems添加到其构造函数中。 public class Animatio…

matlab中CH指标聚类评价指标,MATLAB聚类有效性评价指标(外部)

MATLAB聚类有效性评价指标(外部)作者&#xff1a;凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/更多内容&#xff0c;请看标签&#xff1a;MATLAB、聚类前提&#xff1a;数据的真实标签已知&#xff01;1. 归一化互信息(Normalized Mutual information)定义程序functio…

学习进度表

周数 专业学习目标 专业学习时/每分钟 新增代码量 知识技能总结 第六周 ps的图像处理 80 30 看书加以实践 第七周 数据结构的链式结构 100 50 多做习题加以巩固知识 第八周 网页设计 80 30 多多练习&#xff0c;学会用代码设计 第九周 图片美工 70 30 慢慢学会运用软…

Axis通过wsdd部署Web Service

axis网上的教程很多&#xff0c;不过搜来搜去&#xff0c;总是只有那么几篇。仔细看了一下那几篇文章&#xff0c;都感觉到不是自己想要的&#xff0c;所以自己整理了一篇分享一下。 本文介绍axis应用的一个小例子&#xff0c;没有麻烦的命令行操作&#xff0c;只需照下面的步骤…

弹簧特性

1.概述 本教程将展示如何通过XML或Java配置在Spring中设置和使用属性 。 在Spring 3.1之前 &#xff0c;将新的属性文件添加到Spring并使用属性值并不像它那样灵活和健壮。 从Spring 3.1开始 &#xff0c;新的Environment和PropertySource抽象大大简化了此过程。 2.通过XML名…

php-cgi cpu很高,php-cgi占用cpu资源过高的解决方法

转的网上的&#xff0c;不过对PHP-CGI菜鸟的人&#xff0c;还是有点帮助的。1. 一些php的扩展与php版本兼容存在问题&#xff0c;实践证明 eAccelerater与某些php版本兼容存在问题&#xff0c;具体表现时启动php-cgi进程后&#xff0c;运行10多分钟&#xff0c;奇慢无比&#x…