Socket粘包和拆包处理思路

一旦客户端和服务器建立了Socket通信连接,接下来粘包和拆包就是一个必须要考虑的问题

本文是关于使用TCP协议下Socket粘包和拆包的处理思路

一个大前提:TCP协议是可靠的,数据包一定会到达(99.9%的情况下),而且是按顺序到达,所以就不需要考虑UDP协议丢包和乱序的问题

一个小前提:TCP协议会根据数据包的大小和网络通讯状况对数据包合并发送或分片(分包),一个重要的尝试就是大于MTU值的数据包一定会被分割,因此当数据包到达时会出现两种情况:1、和其他数据包的一部分或者整体连成一个大包,2:被分割成几个小包先后到达

因此,为了确定每个包的起始位置,需要在要发送的数据前面加上包头,包头里一般记录了数据的长度,复杂一点了要加上压缩标志位和CRC校验位等信息,以便于检错。更严格的情况下还会加上包尾

首先从缓冲流中读取一个包头的长度(假设是4个字节),如果连一个包头都读不出来,要么是连接中断了(处理异常,检查心跳,进入超时等待),要么是网络有延迟需要继续接收

解析包头数据,得到包体长度

进入读取循环

判断缓冲流中剩余的数据长度是否大于包体长度

大于等于(粘包的情况),则读取一个包体,然后将缓冲流清空,将剩余数据写回缓冲流(其实就是改变流指针的位置) 然后继续读取下一个包头

小于(被拆分了),则跳出读取循环,继续等待下一次数据接收(可以是异步等待)

对于连接断开,可以分为服务器知道客户端断开(客户端主动用四次挥手和服务器断开),和不知道客户端断开(拔网线),前一种情况走正常流程就可以了,后一种情况下有时链路层会通知网络层,进而抛出异常,比如16001,处理之。可靠的做法还是使用心跳检测,设定在若干秒后没有收到心跳包,就由服务器主动结束这个连接

你可能感兴趣的:(Socket粘包和拆包处理思路)