在前面实现了一个基本的网络通信流程,但在实际网络传输过程中存在很多其他的问题

缓冲区

输入输出流缓冲器,如果你学习过C或C++应该有听说过类似的东西,它的作用时将用户指令进行延时,在系统资源空闲时自动调用,有点类似线程池的感觉。
在网络通信中,发送数据/接收数据都使用缓冲池的概念。
在之前我们使用Socket的Send和Receive方法都只是将指令发给缓冲池,具体我们的请求什么时候执行是由计算机进行动态的分配和调度的

半包&粘包

  • 如果客户端一次发送多条数据,服务器没有及时接受,这些数据都会写入缓冲区,在服务器接收时就会一次性收到之前未收到的多条数据;这就造成了,包和包粘在一起的粘包现象的发生。
  • 如果客户端发送大量的信息,服务器一次解析并没有获得所有数据(缓冲区容量不够),那这样就只会接受到部分信息;这就造成了,半包现象。

解决方法

长度信息法

在每个数据包前面都加上长度信息。每次接受数据时,先获取该条完整数据的理论长度,如果缓冲区的数据长度大于理论长度,就取出对应字节;如小于,说明数据不完整,等待下一次数据接收。
我画了一个图来表示:

从图中我们可以看出,第一次接收时,并没有接收到完整的信息,但是我们可以通过长度值,在下次接收欠缺的数据,直到数据接受完毕。

固定长度法

每次都以相同的长度发送数据,假设发送的数据长度为5那么,发送Hi就需要发送Hi+3个长度的占位字符如“Hi...”。
接收方每次都接收固定长度的数据,作为一条消息来处理,假设读取到的数据大于5说明存在多条数据,不断的以5位长度取出数据即可。假设,不为5的倍数,就等待下一次数据。

结束符号法

规定一个符号作为消息的结束符,用以间隔消息,在读取时,如果消息中没有出现结束符,说明消息没有发生完,等待下次消息。如果消息中有结束符则根据结束符分隔消息即可。