多人在线斗地主游戏开发——自定义TCP网络通信协议包格式

    什么叫做通信协议什么制定通信协议怎么制定通信协议不知道大家有没有迷茫过这个问题,反正我是有的,,,

    想我在刚接触网络编程的时候,是linux下用socket懵懵懂懂地按照pdf书籍上的代码敲了个非常简单的C/S架构的 聊天程序,

Client端发一个字符串,服务器接收到打印后,再返回一个字符串,敲完了后,自己运行着这个‘很牛 很高大上’的程序,玩得不亦乐乎,同时脑子里迸发了一大堆的想法,终于会网络编程了,之前写的程序只能在本地运行,现在应该可以利用socket写出网络通信的程序了,我可以把自己写的‘游戏’、‘软件’发给远在他方的朋友,一起联网运行(事实上,想多了,理想是丰满的,现实是异常骨感的)。

      经过了一番思考,动手利用socket写了个简单的发送文件的程序,Client发送FileName至Server, Server收到后返回“OK”,然后Client开始读取文件数据,并send.

      其实这里的Client发送FileName,服务器返回OK,  可以说就是所谓的通信协议了,只不过是简陋得有点可怜的通信协议。

       通信协议,实际上就是一种通信的约定,我发什么数据给你,你根据我发的这个数据,要返回什么数据给我,例如下面这个不是很好的例子:

           

多人在线斗地主游戏开发——自定义TCP网络通信协议包格式

 

       上面就是一个简单登录协议, 开发者在动手敲代码之前,就已经规定了Client会发送哪些数据,服务器要怎样响应数据,如Client 发送‘用户名和密码数据,验证登录’,  Server收到后根据协议,就知道这条指令是什么意思,需要我做什么事情,然后我做完了之后该怎么返回结果给Client, 按照上面定好的协议,Server如果验证成功,则返回B 代表的指令,  如果验证失败,则返回C代表指令,而且只能返回这两者其一,不能返回其他数据, 一般协议之外的其他消息数据应该被程序认为是不合法的数据,无效的数据。

      如果Server返回的是B, 那么Client就知道账户密码正确,登录成功了,如果B的指令数据中含有Hall Server(大厅服务器)的IP和Port的话, Client就知道,它可以连接游戏大厅了

      如果Server返回的是C, 那么Client就知道验证失败了,就会做失败的处理。

      所以,通信协议就是一个约定,一个规定,一份对应的请求和响应指令,我发送什么指令给你,你根据我的指令判断 你需要做什么操作,然后根据协议约定的返回结果的数据格式,返回结果给我,我收到你的返回,根据协议上的约定,我就知道接下来我该怎么去做。

       那到这里了,大家可能想问了,在我不知道什么是通信协议的时候,我就已经在用着了,就像上面发送文件的程序一样,我发个字符串给服务器,服务器给我返回一个字符串就行了,那我就按照这样就可以了,何必要再花时间费脑子去制定一个协议呢/p>

       那不知道大家在写socket TCP程序的时候,有没有遇到过粘包的问题,那时候我和两个同学,写一个局域网斗地主游戏,在tcp通信的时候,经常会遇到这个问题,当Client有连续发送“OK”、“bige”两条消息给服务器的时候,理想状态是,服务器接收到“OK”,然后做相应处理,然后接收到“bige”,再做相应处理, 而实际上呢,服务器接收到的是“OKbige”, 然后导致服务器不知道这是条什么命令,然后无任何相应,甚至出错。

        socket Tcp是流式地发送数据,没有上一条数据和下一条数据之间的界限,属于是水乳交融,无缝连接的。

        那么该怎么解决连包的问题呢nbsp;

        我们可以通过制定一份通信协议来解决连包问题,同时也大大降低程序通信的混乱性,提升代码可读性和健壮性。

        通过阅读了多个开源游戏服务器的网络通信模块,以及一些文档资料,我大概确定怎样制定一份协议,(我知道这可能不是一份完美的协议格式,可能存在一些问题,如果有何建议的话,恭请不吝指教)如下:

        一条协议数据应该由三部分组成:协议头  + 指令数据 + 校验码

            1)协议头:    必须固定大小为多少字节,例如:

    

多人在线斗地主游戏开发——自定义TCP网络通信协议包格式

            有了协议头后,解析协议数据的时候,先接受10个字节的协议头数据,然后在协议头中解析指令类型,再解析指令数据长度length,然后再读取length个字节的数据,这length个字节的数据就是一条单独的指令,后面还有数据的话,就等下次解析了。

           2)指令数据: Client与Server之间具体的请求响应交互操作

           3)校验码:

                校验码一是校验协议包的完整性,二是校验协议包的合法性,防止有其他人恶意 发送消息给Server,造成Server的资源消耗等

        所以完整的协议格式应该如下(序号可以视情况选择用不用):

多人在线斗地主游戏开发——自定义TCP网络通信协议包格式

       发送方 根据此协议格式组织 协议包,发送给接收方,接收方接收后的解析步骤:

              1)读取10字节协议头, 解析出指令长度len

              2)接着后面读取len个字节的数据,此时,已经读取了len+10字节数据,刚好就是一个完整的协议包

              3)将前len+10-2个字节数据,进行校验算法的校验,生成出两字节的校验位

              4)将生成的校验位与接收到的协议包中的校验位进行比较,如果相同则,指令正确,如果不同,则校验失败,数据异常,可以选择丢掉数据等处理

              5)校验成功后,根据协议包中的指令类型,将指令分发到对应功能的接口模块,进行处理。

        此外,通常情况下,为了防止tcp通信的协议包被抓包破解,泄漏程序的业务流程,造成极大的安全隐患,在发送组织好的协议包之前,还会用加密算法,将指令数据进行加密,然后再发送至接收端,接收端,先进行解密,再效验数据。

 

        网络通信中用到的通信格式,还有Json、XML、谷歌的protobuf等等

 

 

 

 

 

 

 

 

 

 

 

 

 

 

   

来源:春休夏末

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2019年6月13日
下一篇 2019年6月13日

相关推荐