diff --git a/blogs/computer_network/口水话/TCP.md b/blogs/computer_network/口水话/TCP.md index 5d24b6f..95c3404 100644 --- a/blogs/computer_network/口水话/TCP.md +++ b/blogs/computer_network/口水话/TCP.md @@ -9,8 +9,8 @@ TCP 口水话 3. 三次握手 4. 四次挥手 5. 重传机制 -6. 滑动窗口 -7. 流量控制 +6. 流量控制之滑动窗口 +7. 拥塞控制 #### 概述 @@ -18,7 +18,7 @@ TCP 是一个可靠的、面向连接的、基于字节流、全双工的协议 面向连接的协议要求正式发送数据之前需要通过握手建立一个逻辑连接,结束通信时也是通过有序的四次挥手来断开连接。 -TCP 协议是可靠的,而 IP 是一种无连接、不可靠的协议。IP 协议尽最大可能将数据报从发送者传输给接受者,但并不保证包到达的顺序会与它们被传输的顺序一致,也不保证包是否重复,甚至都不保证包是否会到达接受者。TCP 要想在 IP 的基础上构建可靠的传输层协议,必须有一个复杂的机制来保障可靠性,主要有:对每个包提供校验和、包的序列号解决了接收数据的乱序、重复问题、超值重传机制以及流量控制、拥塞控制。 +TCP 协议是可靠的,而 IP 是一种无连接、不可靠的协议。IP 协议尽最大可能将数据报从发送者传输给接受者,但并不保证包到达的顺序会与它们被传输的顺序一致,也不保证包是否重复,甚至都不保证包是否会到达接受者。TCP 要想在 IP 的基础上构建可靠的传输层协议,必须有一个复杂的机制来保障可靠性,主要有:对每个包提供校验和、包的序列号解决了接收数据的乱序、重复问题、超时重传机制以及流量控制、拥塞控制。 TCP 是面向字节流的协议,流的含义是没有固定的报文边界,这就需要应用程序定义自己的消息分隔符,比如 HTTP 中的 \r\n。 @@ -44,13 +44,13 @@ PSH:告知对方这些数据包收到以后应该马上交给上层应用, #### 三次握手 -![img](https://user-gold-cdn.xitu.io/2019/6/13/16b518ccedac1b6e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) +![img](https://i.loli.net/2020/07/15/tix53GJq2dLgpsh.jpg) 三次握手的最重要的就是交换彼此的 ISN(初始序列号)。客户端会随机选择一个数字作为初始序列号。SYN 报文不携带数据,但是它占用一个序号,下次发送数据序列号要加一。之所以要消耗一个序列号是因为它需要对端确认,不占用序列号的段是不需要确认的,比如 ACK。总结来说,凡是消耗序列号的 TCP 报文段,一定需要对端确认,如果这个段没有收到确认,会一直重传直至到达指定的次数为止。 除了交换彼此的初始序列号,三次握手的另一个重要作用是交换一些辅助信息,比如最大段大小 MSS、窗口大小 Win、窗口缩放因子 WS 等。 -![img](https://user-gold-cdn.xitu.io/2019/6/13/16b518cd1664fa5d?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) +![img](https://i.loli.net/2020/07/15/vPrqH8C3cd9gn5K.jpg) 当客户端发送 SYN 到对端,服务端收到后会回复 SYN+ACK,此时会将连接信息放入半连接队列,服务端同时会开启一个定时器,如果超时还未收到 ACK 就会进行 SYN+ACK 重传。一旦收到客户端的 ACK,服务端就开始尝试把它加入另一个全连接队列。 @@ -58,7 +58,7 @@ SYN 洪水攻击就是客户端伪造 IP 发送 SYN 包,服务端回复的 ACK #### 四次挥手 -![img](https://user-gold-cdn.xitu.io/2019/6/26/16b911c618264239?imageView2/0/w/1280/h/960/format/webp/ignore-error/1) +![img](https://i.loli.net/2020/07/15/nHAtjNGDKZbO1UQ.jpg) FIN 同 SYN 报文一样,不管是否携带数据,FIN 段都需要消耗一个序列号,如果 FIN 段不消耗序列号,那么在客户端收到 ACK 报文时是不知道是 Data 的确认包还是 FIN 的确认包。 @@ -80,3 +80,10 @@ FIN 同 SYN 报文一样,不管是否携带数据,FIN 段都需要消耗一 #### 滑动窗口 +TCP 会把要发送的数据放入发送缓冲区,接收到的数据放入接收缓冲区,应用程序会不停的读取缓冲区的内容进行处理。流量控制做的事情就是,如果接收缓冲区已满,发送端应该停止发送数据,那发送端怎么知道接收端缓冲区是否已满呢?为了控制发送端的速率,接收端会告知客户端的自己的接收窗口(rwnd),TCP 在收到数据包回复的 ACK 包里会带上自己接收窗口的大小,客户端需要根据这个值调整自己的发送策略。 + +由此引入两个状态,TCP window full 与 TCP zero window。TCP Window Full 是站在发送端角度说的,表示在途字节数等于对方接收窗口的情况,此时发送端不能再发数据给对方直到发送的数据包得到 ACK。TCP zero window 是站着接收端角度来说的,是接收端接收窗口满,告知对方不能在发送数据给自己。 + +#### 拥塞控制 + +前面介绍了 TCP 利用滑动窗口来做流量控制,流量控制这种机制确实可以防止发送端向接收端过多的发送数据,但是它只关注了发送端和接收端自身的状况,而没有考虑整个网络的通信状况。 \ No newline at end of file