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

我们这边是一个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,这个函数本身就可以用在二进制读取。

1 2 收藏 评论

关于作者:徐汉彬

现任腾讯高级工程师(T3-2),QQ会员体系合作线技术团队负责人,负责生活特权和AMS平台(高峰期CGI日请求12亿),曾就职于阿里巴巴、小满科技。 个人主页 · 我的文章 · 54 ·   

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部