您的位置:首页 > 理论基础 > 计算机网络

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

2017-03-16 22:26 225 查看
我们这边是一个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使用的库文件pb_proto_scintf.php,下一步就是编写实际的程序代码。


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

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

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


 

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

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


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



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

解决的方式,其实也很简单,就是直接使用fread,这个函数本身就可以用在二进制读取。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: