什么是粘包/拆包
TCP是个“流”式的协议,会根据TCP缓冲区的实际情况进行包的划分。在业务层面认为一个完整的包,可能会被TCP拆分成多个小包进行发送,也可能把多个小的包封装成一个大的数据包进行发送
粘包拆包问题解决方法
由于TCP协议底层无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,所以,这个问题只能通过上层的应用层协议设计来解决,常见方案如下:
(1)消息定长,发送方和接收方规定固定大小的消息长度,例如每个报文大小固定为200字节,如果不够,空位补空格;
(2)在包围增加特殊字符进行分割,例如FTP协议;
(3)自定义协议,将消息分为消息头和消息体,消息头中包含消息总长度,这样服务端就可以知道每个数据包的具体长度了,知道了发送数据包的具体边界后,就可以解决粘包和拆包问题了;
为什么UDP不会发生粘包/拆包问题?
接收端的缓冲区采用了链式结构来缓存每一个到达的数据包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。即面向消息的通信是有消息边界的。所以udp根本不会粘包。
Http怎么解决拆包粘包的?
http请求报文格式
1)请求行:以\r\n结束;
2)请求头:以\r\n结束;
3)\r\n;
3)数据;
http响应报文格式
1)响应行:以\r\n结束;
2)响应头:以\r\n结束;
3)\r\n;
4)数据;
1)遇到第一个\r\n表示读取请求行或响应行结束;
2) 遇到\r\n\r\n表示读取请求头或响应头结束;
3)怎么读取body数据呢?
根据请求头或响应头的Content-Length,单位是字节;
chunked协议,取代Content-Length,如果请求头或者响应头有Transfer-Encoding: chunked,表示根据chunked协议协议读取数据,具体如下:
读取第一个chunk,遇到CRLF表示读取长度完毕,接下来是第一个chunk的数据,也是以CRLF结束。当遇到长度为0的chunk,表示数据读取完毕。
两种方式区别