-
如何理解字节流
-
为什么 UDP 是面向报文的协议?
-
当用户消息通过 UDP 协议传输时,操作系统不会对消息进行拆分
-
每个 UDP 报文就是一个用户消息的边界
-
接收方在接收到 UDP 报文后,读一个 UDP 报文就能读取到完整的用户消息。
-
如果收到了两个 UDP 报文,操作系统是怎么区分开的?
-
操作系统在收到 UDP 报文后,会将其插入到队列里,队列里的每一个元素就是一个 UDP 报文,这样当用户调用系统调用读数据的时候,就会从队列里取出一个数据,然后从内核里拷贝给用户缓冲区。
-
-
-
为什么 TCP 是面向字节流的协议?
-
当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文
-
接收方的程序如果不知道发送方发送的消息的长度,也就是不知道消息的边界时,是无法读出一个有效的用户消息的
-
因为用户消息被拆分成多个 TCP 报文后,并不能像 UDP 那样,一个 UDP 报文就能代表一个完整的用户消息。
-
我们不能认为一个用户消息对应一个 TCP 报文,正因为这样,所以 TCP 是面向字节流的协议。
-
当两个消息的某个部分内容被分到同一个 TCP 报文时,就是我们常说的 TCP 粘包问题,这时接收方不知道消息的边界的话,是无法读出有效的消息。
-
-
如何解决粘包
-
粘包的问题出现是因为不知道一个用户消息的边界在哪,如果知道了边界在哪,接收方就可以通过边界来划分出有效的用户消息。
-
一般有三种方式分包的方式:
-
固定长度的消息
-
特殊字符作为边界
-
自定义消息结构
-
-
固定长度的消息
-
最简单方法
-
每个用户消息都是固定长度的,比如规定一个消息的长度是 64 个字节,当接收方接满 64 个字节,就认为这个内容是一个完整且有效的消息。
-
但是这种方式灵活性不高,实际中很少用
-
-
特殊字符作为边界
-
可以在两个用户消息之间插入一个特殊的字符串,这样接收方在接收数据时,读到了这个特殊字符,就把认为已经读完一个完整的消息。
-
注意,这个作为边界点的特殊字符,如果刚好消息内容里有这个特殊字符,我们要对这个字符转义,避免被接收方当作消息的边界点而解析到无效的数据
-
-
自定义消息结构
-
可以自定义一个消息结构,由包头和数据组成,其中包头包是固定大小的,而且包头里有一个字段来说明紧随其后的数据有多大。
-
-
-