设计一个简单的socket通信协议

时间:2021-12-16 20:03:50

为什么要设计一个协议呢?因为TCP协议是面向字节流的协议,面向字节流的协议是无边界的,也就是说一次发送操作并不一定就仅仅产生一个数据包,而有可能是多个,在接收端不一定一次接收就能完成所有数据的收操作。这样如果服务端和客户端没有通信协议,则客户端发送完数据之后,服务端不知道需要经过几次接受(receive)操作才能完成一次数据交换。

这个问题一般发生在客户端和服务端传送大批量数据时,如果数据之间没有边界,那么服务端如何知道数据已经传送完毕了呢?

所以,为了传送大量数据,或者客户端与服务端延迟较大时,需要设计通信协议,来保证数据正确发送和接受。

为了是接收方能正确理解发送方需要发送的数据,即发送一次发送多少,接收方就应该接受多少,一般有两种方法:

第一种:在每个发送操作前,加上数据包的长度,这样,服务端接受时,只有完全收到了对应长度的数据量,才能算一次receive操作完成

第二种:设置分隔符,在数据的最后设置分隔符,服务端从开始接受到读到分隔符才算一次操作完成

安全性考虑:对于第一种协议方式,如果攻击者把数据量的长度设置特别大,可能会造成接收方长时间接收无用的攻击数据,最终造成buffer溢出

对于第二种协议方式,攻击者构造没有分隔符的数据包,也会造成接收方一直接受,最终造成buffer溢出

所以在设计socket协议的时候必须要考虑一点的就是服务端对于一次接收操作的数据量应该设置一个上限。

是否需要数据校验:

TCP协议能保证数据从发送缓冲区到接收缓冲区是有序无误的,而应用从缓冲区读入的时候,可能数据已经被人篡改了,如果要完全保证应用数据安全性,则在应用上层还是要做TCP Sokcet的数据校验。

于是,设计出来的通信协议如下:

设计一个简单的socket通信协议

  • Type指的是数据包类型,可以指定数据包用来的目的
  • Data Length指的是数据的长度
  • Data 数据体
  • CS 校验,包括Type、Data Length和Data的校验,一般可以用md5校验

原文:https://github.com/Charles0429/a_simple_weibo_server/blob/master/weibo_server/protocol.md