UDP协议格式
UDP 报文分为 UDP 报头和 UDP 数据区两部分。报头由 4 个 16 位长(2字节)字段组成,分别说明该报文的源端口、目的端口、报文长度和校验值。
UDP协议如何将报头和有效载荷分离
UDP报头是一种定长报头,长度为8个字节。UDP在读取报文时,首先读取这8个字节的报头,剩下的部分就是有效载荷。
特点
1.无连接:知道两端的ip和端口即可直接传输
2.不可靠:没有确认机制,没有重传,因为网络故障无法发送到对方,UDP协议层也不会返回任何错误信息。
3.面向数据报:应用层交给UDP多长的报文,UDP原样发送,既不拆分也不合并。(如果发送端调用一次sendto发送100个字节,接收端必须调用一次recvfrom接收100个字节;而不能循环调用10次每次10个)
UDP的缓冲区
UDP没有真正意义上的 发送缓冲区. 调用sendto会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作;
UDP具有接收缓冲区. 但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一致; 如果缓冲区满了, 再到达的UDP数据就会被丢弃;
TCP协议格式
应用层对数据处理,调用write,sendto等接口将数据从用户缓冲区发送到传输层TCP的发送缓冲区,由TCP协议决定数据怎么发,发错了怎么办。接收缓冲区收到数据,由read,recv等接口读到用户级缓冲区。
窗口大小
16位窗口大小是自己的接收缓冲区剩余大小,用于流量控制。
接收端在对发送端发送过来的数据进行响应时,可以通过 TCP 的报头中的 16 位窗口大小来告知发送端自己当前接收缓冲区剩余空间的大小。此时,发送端就可以根据这个窗口大小来调整自己发送数据的速度。
窗口大小字段越大,说明接收端处理数据的能力越强,发送端可以适当地提高数据的发送速度。
窗口大小字段越小,说明接收端处理数据的能力越弱,发送端需要适当地降低数据的发送速度。 当窗口大小字段等于 0
时,说明接收端的接收缓冲区已经没有剩余空间了,发送端应该停止发送数据直到接收端处理完一些数据,接收缓冲区中有空间剩余。 通过 16 位窗口大小告知对方自己的接收能力,这样就可以做到流量控制了。
- 在进行套接字编程时,我们调用 write / send函数向套接字中写入数据时,可能会因为套接字的发送缓冲区已经被写满而被阻塞住了,其本质就是 TCP 中的发送缓冲区已经被写满了,所以write / send 函数就需要阻塞到发送缓冲区有足够的空间来存储数据。
- 我们调用 read / recv 函数从套接字中读取数据时,可能会因为套接字中的接收缓冲区中没有数据而被阻塞住了,其本质就是 TCP 中的接收缓冲区中没有数据,所以read / recv 就需要阻塞到接收缓冲区中有一定数量的数据。
- 调用 write / send 和 read / recv函数会被阻塞注,本质就是生产者消费者模型中的临界资源没有就绪,需要阻塞等待直到条件满足。
如何将报头和有效载荷分离?
固定长度+自描述字段
读取报文的前20个字节:当TCP获取到一个报文后,首先会读取报文的前20个字节。这20个字节包含了TCP报头的基本信息,如源端口号、目的端口号、序列号、确认号等。
提取首部长度字段:在这20个字节中,TCP会提取出4位的首部长度字段。这个字段表示的是TCP报头的总长度,单位是4字节。因此,通过读取这个字段,TCP就可以知道报头的实际大小(size)。
判断是否存在选项字段:如果首部长度字段表示的大小(size)大于20字节,那么就说明TCP报头中还包含了选项字段。选项字段是可选的,它包含了一些用于控制TCP连接行为的参数。
读取选项字段:如果存在选项字段,TCP就需要继续从报文中读取size -20字节的数据。这部分数据就是TCP报头中的选项字段。选项字段的长度可以是0到40字节之间(因为TCP报头的最大长度是60字节,基本报头长度是20字节)。
分离有效载荷:读取完TCP的基本报头和选项字段后,剩下的部分就是有效载荷了。有效载荷是TCP报文的实际数据部分,它承载了应用层要传输的信息。
理解确认应答机制
发送方首先进行序列号分配,将数据分成tcp段的较小单元,并为每一个分段分配一个唯一的序列号,发送给接收方同时也会启动一个计时器,接收方接收到数据会回复一个ACK(确认序号),采用累计确认的方式即可以接收到多个数据包再发送一个累计的ACK。
重传机制:如果在计时器规定的时间内没有发送方没有收到应答便会重传数据包。
滑动窗口:允许接收方在发送一个ACK之前接收多个数据包,而不仅仅是接收一个数据包就发送一个ACK。
选择性确认(SACK):虽然TCP主要使用累积确认,但还支持一种称为选择性确认(SACK)的扩展。使用SACK,接收方可以明确地告诉发送方哪些数据包已经成功接收,哪些数据包丢失了,从而允许发送方只重传丢失的数据包,而不是整个数据流。
快速重传和快速恢复:当接收方收到一个乱序的数据包时,它会立即发送一个重复的ACK,这个重复的ACK的确认号仍然指向期望接收的下一个字节的序号。如果发送方收到三个或更多的重复ACK,它会触发快速重传机制,即立即重传缺失的数据包,而不需要等待重传超时。快速恢复是与快速重传一起使用的机制,它允许发送方在重传数据包之后立即回到之前的传输状态,而不是像正常重传那样进入慢启动阶段。