注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

技术行者

时代的车轮在按照摩尔定律滚动。

 
 
 

日志

 
 

PHP接入Protocol Buffer并且实现TCP的二进制流传输  

2015-07-24 16:37:50|  分类: PHP |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

我们这边是一个PHP的Web系统,需要新接入一个业务,是通过Protocol Buffer协议通信,而且只提供了一个C++的接入例子。 对于我们的PHP系统来说,除了接入Protocol Buffer之外,还需要处理二进制流的TCP传输通信,而PHP实际上并不太擅长做这些事情。

PHP版本的Protocol Buffer接入,有官方的支持实现版本。

Protocol Buffer for PHP:

https://code.google.com/p/pb4php/

这里需要注意的点,就是安全中心提供的proto文件里面有一些东西是我们的PHP无法识别的。

(1)头部的package,无法识别直接注释掉。

(2)pb_parser文件里的标量类型做一下调整,之后就可以顺利生成我们需要使用的PHP库文件哈。

PHP接入Protocol Buffer并且实现TCP的二进制流传输 - 徐汉彬Hansion - 技术行者

 

生成的代码:

require_once('./parser/pb_parser.php'); 
$test = new PBParser(); 
$test->parse('scintf.proto');

 于是,我们得到了PHP使用的库文件pb_proto_scintf.php,下一步就是编写实际的程序代码。

PHP接入Protocol Buffer并且实现TCP的二进制流传输 - 徐汉彬Hansion - 技术行者

 

我们经常使用PHP来做字符串的socket通信,但是,处理这种二进制格式的socket传输,PHP并不太擅长。

我们也只能通过pack/unpack的方式,来将字符串转为二进制流。将传输字符串pack为二进制,传输出去,获取回包后,在unpack为字符串,再进行处理。

http://php.net/manual/zh/function.pack.php

PHP接入Protocol Buffer并且实现TCP的二进制流传输 - 徐汉彬Hansion - 技术行者

 

在这里,因为我们的PHP是安装了内部的扩展的,我们刚开始犯了一个小错误,就是直接使用了内部类,读取socket回包内容直接使用了read_line(内部实现其实是fgets)。这种做法,会引起2个问题:

(1)当TCP传输只有1个内容数据包的时候,read_line能够读取全部内容,在后续的unpack操作中,一切正常那个。但是,当TCP传 输的超过1个内容数据包的时候,read_line只能读取到第一个包的内容,后面的包没有获取到,在unpack的时候,会报头部解析出来的长度和实际 数据内容大小对不上。

PHP接入Protocol Buffer并且实现TCP的二进制流传输 - 徐汉彬Hansion - 技术行者
 

这个有点奇怪的现象,我们是通过tcpdump抓包分析后发现的:

PHP接入Protocol Buffer并且实现TCP的二进制流传输 - 徐汉彬Hansion - 技术行者

(2)read_line是按照行读取内容,而二进制流中不会以换行符结束,因此,这里还会引起read socket timeout,虽然我们也能顺利读取到内容。

解决的方式,其实也很简单,就是直接使用fread,这个函数本身就可以用在二进制读取。

  评论这张
 
阅读(978)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017