如何理解TCP是面向字节流协议
之所以说TCP是面向字节流协议,UDP是面向报文协议。主要是因为发送方的发送消息的机制不同
UDP是面向报文协议
udp在发送消息时,在传输层直接就将一个消息打包成一个完整的包,组装好udp头部,不进行切割,就转发给网络层。也就是每一个UDP报文就是一个消息
。服务端在接收到udp报文时,会将它放到一个队列中,一个元素就是一个udp报文。每次读取时,读取一个元素
TCP是面向字节流协议
当tcp在传输层发送消息时,一个消息可能会被分割成多个tcp报文进行转发给网络层。我们不能认为一个tcp报文就是一个消息,所以tcp是面向字节流协议
由于一个消息对应的不是一个tcp报文,如果接受方不知道一个消息的长度或者分割的边界在哪里,就会无法组装成一个消息,这就形成了粘包问题
粘包问题解决
三种方式:
- 固定长度的消息
- 特殊字符当做边界
- 自定义消息结构
固定长度的消息
将消息长度固定,比如规定一个消息长度为64字节,那么只要接收到了64字节,就认为这个内容是一个完整的消息
特殊字符作为边界
我们可以在两个消息之间加入一个特殊字符,如果读到了这个特殊字符,则认为一个消息已经完整的接收到了。
比如我们的http
HTTP通过回车换行来判断消息边界。
需要注意的是,如果消息内容中含有分割消息的特殊字符的话,需要进行转义处理,否则则会错误判断消息边界
自定义消息结构
我们可以自定义消息结构,由包头和数据来构成,包头里有一个字段表示紧随其后的一个消息有多大。
当接收方接收到包头时,就会解析包头里的数据长度,接下来就读取数据,知道读取到指定长度时,就是一个完整的消息