最近在对接一个外设,这个外设通过TCP/IP 协议和服务器交换数据。这里简单摘抄了几条控制命令和消息:
1. 保活
S
2. 向服务器登录
START login type='ES0001TVAPW' id='5d7ff303832473143227616' device='espeed138' user='admin' password='check='237' END user='admin' password='check='237' END
3. 向服务器汇报IO 状态
START iostate total='8' io8='254' check='86' END
4. 向服务器汇报内部信息
START PVC_Info p='806' v='27558' c='36' tflag='0' END
START PVC_Info p='806' v='27558' c='36' tflag='1' t='202' f='683' h='356' check='137' END
5. 服务器获取外设内部信息
START PVC_get check='136' END
6. 服务器关闭IO
START close io='1' check='202' END
7. 向服务器汇报日程
START programme1 p_name1='12' frequency1='49' p_action1='49' p_delay1='0' socket[0]1='15' socket[1]1='0' socket[2]1='0' p_state1='49' p_id1='48' p_calendar1='2014010100001' p_name2='' frequency2='48' p_action2='48' p_delay2='0' socket[0]2='0' socket[1]2='0' socket[2]2='0' p_state2='48' p_id2='48' p_calendar2='' p_name3='' frequency3='48' p_action3='48' p_delay3='0' socket[0]3='0' socket[1]3='0' socket[2]3='0' p_state3='48' p_id3='48'p_calendar3='' p_name4='' frequency4='48' p_action4='48' p_delay4='0' socket[0]4='0' socket[1]4='0' socket[2]4='0' p_state4='48' p_id4='48' p_calendar4='' p_name5='' frequency5='48' p_action5='48' p_delay5='0'socket[0]5='0' socket[1]5='0' socket[2]5='0' p_state5='48' p_id5='48' p_calendar5='' check='85' END
怎么样才能快速优雅的解析协议?你觉得你需要花多久?
对于有经验的程序员,只需要二三十分钟左右。其实元编程(Meta Programming)非常适合解决此类问题,最后写好的代码是一个大型的表查询(Table Driven)。我们使用的语言是PHP,下面是对这个协议的解析。
一、处理消息粘滞,一般协议在设计时就规定了怎么处理粘滞,比如SMTP 和HTTP 协议都采用CRLF,我们对接的这个设备采用的是LF(CR 即\r,LF 即\n)。
二、保活消息
三、验证消息合法性
我们判断是否以"START " 开头并且以" END" 结尾。
四、主体代码
保活消息是个例外,我们特别处理一下,然后就调用通用的解析函数。
五、解析
一般的协议都会分消息和控制命令两部分,我们这么定义:
基于元编程的思想,我们只需要编写基础的解析函数,然后通过数据(表)来控制协议的解析。在这里我们写了两个基础函数 _parse_cmd 解析命令部分,_parse_args 解析参数部分,而parse_msg 负责解析整个消息。
我们的表设计为这样,因为这份协议比较简单,所以这张表也比较简单。但是类似构造Intel 32位架构反汇编器的情况,表就会比较复杂了。
到此为止,整个协议的解析就结束了,整个代码思路非常清晰,也很优雅,希望能对你有启发。
网友评论