diff --git a/notes/pics/tcp-sack.gif b/notes/pics/tcp-sack.gif new file mode 100644 index 00000000..0dc89abf Binary files /dev/null and b/notes/pics/tcp-sack.gif differ diff --git a/notes/计算机网络 - 传输层.md b/notes/计算机网络 - 传输层.md index 0edee9c5..8c5c5451 100644 --- a/notes/计算机网络 - 传输层.md +++ b/notes/计算机网络 - 传输层.md @@ -1,23 +1,23 @@ # 计算机网络 - 传输层 * [计算机网络 - 传输层](#计算机网络---传输层) - * [UDP 和 TCP 的特点](#udp-和-tcp-的特点) + * [UDP 和 TCP 的特点](#udp-和-tcp-的特点) 🔥🔥 * [选择 TCP 还是 UDP](#选择-tcp-还是-udp) * [UDP 首部格式](#udp-首部格式) * [TCP 首部格式](#tcp-首部格式) - * [TCP 的三次握手](#tcp-的三次握手) + * [TCP 的三次握手](#tcp-的三次握手) 🔥🔥 * [三次握手的原因](#三次握手的原因) * [握手报文丢失](#握手报文丢失) - * [TCP 的四次挥手](#tcp-的四次挥手) + * [TCP 的四次挥手](#tcp-的四次挥手) 🔥 * [四次挥手的原因](#四次挥手的原因) * [TIME_WAIT](#time_wait) * [大量 TIME_WAIT 与 CLOSE_WAIT](#大量-time_wait-与-close_wait) - * [TCP 可靠传输](#tcp-可靠传输) + * [TCP 可靠传输](#tcp-可靠传输) 🔥 * [确认与重传](#确认与重传) * [超时重传时间](#超时重传时间) * [TCP 滑动窗口](#tcp-滑动窗口) * [TCP 流量控制](#tcp-流量控制) - * [TCP 拥塞控制](#tcp-拥塞控制) + * [TCP 拥塞控制](#tcp-拥塞控制) 🔥🔥 * [1. 慢开始与拥塞避免](#1-慢开始与拥塞避免) * [2. 快重传与快恢复](#2-快重传与快恢复) * [TCP 粘包与拆包](#tcp-粘包与拆包) @@ -36,7 +36,7 @@ 网络层只把分组发送到目的主机,但是真正通信的并不是主机而是主机中的进程。传输层提供了进程间的逻辑通信,传输层向高层用户屏蔽了下面网络层的核心细节,使应用程序看起来像是在两个传输层实体之间有一条端到端的逻辑通信信道。 -## UDP 和 TCP 的特点 +## UDP 和 TCP 的特点 🔥🔥 - 用户数据报协议 UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信; - 传输控制协议 TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)。 @@ -81,7 +81,7 @@ DNS 也不是只用 UDP。不带 EDNS 扩展时,UDP 上的 DNS 响应限制为 - 终止 FIN:用来释放一个连接,当 FIN=1 时,表示此报文段的发送方的数据已发送完毕,并要求释放连接; - 窗口:窗口值作为接收方让发送方设置其发送窗口的依据。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。 -## TCP 的三次握手 +## TCP 的三次握手 🔥🔥

@@ -109,7 +109,7 @@ DNS 也不是只用 UDP。不带 EDNS 扩展时,UDP 上的 DNS 响应限制为 - 第二次握手的 SYN+ACK 丢失:客户端以为 SYN 丢了,重传 SYN;服务器收不到第三次握手,也重传 SYN+ACK(tcp_synack_retries 默认 5 次,间隔 1、2、4、8、16 秒),任何一方的重传到达,连接都能建立; - 第三次握手的 ACK 丢失:客户端发出 ACK 后已经进入 ESTABLISHED,服务器仍处于 SYN_RCVD,继续重传 SYN+ACK,客户端每收到一次就再回复一次 ACK。客户端发送的数据报文段也带有 ACK,服务器收到后同样会建立连接;如果客户端一直不发数据,服务器重传 5 次后放弃,之后客户端再发数据会收到 RST。 -## TCP 的四次挥手 +## TCP 的四次挥手 🔥

@@ -160,7 +160,7 @@ TIME_WAIT 出现在主动关闭的一方,使用短连接的机器会积累大 CLOSE_WAIT 出现在被动关闭的一方,表示对方已经关闭,本方的应用还没有调用 close()。连接大量停在 CLOSE_WAIT 通常是程序的问题,例如异常分支没有关闭连接、从连接池借出的连接没有归还,需要排查代码,保证每个连接最终都会被关闭。 -## TCP 可靠传输 +## TCP 可靠传输 🔥 IP 层只尽力交付,分组可能出错、丢失、重复或者乱序到达。TCP 在此之上用以下机制保证应用读到的字节流与对方写入的完全一致: @@ -175,17 +175,7 @@ IP 层只尽力交付,分组可能出错、丢失、重复或者乱序到达 TCP 的确认是累积的:确认号为 N 表示 N 之前的字节都已收到。例如发送方连续发出 8 个报文段,每段 1000 字节,第 2 段丢失,双方都支持选择确认(Selective Acknowledgment, SACK): -```text -发送方 接收方 -序号 1~1000 至 7001~8000,共 8 段 → 1001~2000 丢失 - ← ack 1001 - ← ack 1001,SACK 2001~3000 - ← ack 1001,SACK 2001~4000 - …… - ← ack 1001,SACK 2001~8000 -重传 1001~2000 → - ← ack 8001 -``` +

第 3 段到达时,接收方仍然只能确认到 1001,于是重复发送 ack 1001,称为重复确认。发送方收到 3 个重复确认,就知道 1001 开始的这一段丢了,不等超时立即重传,即快重传;接收方补上空洞后,一次确认到 8001。 @@ -252,7 +242,7 @@ RTO = RTTs + 4 × RTTd 首部的窗口字段只有 16 位,最大 65535 字节。在带宽大、延迟高的网络中不够用,例如 RTT 为 100 ms 时,64 KB 的窗口最多只能达到约 5 Mbit/s,而 1 Gbit/s 的链路一个 RTT 内可以发出 12.5 MB。窗口扩大选项在握手时协商一个移位数,实际窗口为窗口字段左移这么多位,移位数最大为 14,窗口最大约 1 GB。 -## TCP 拥塞控制 +## TCP 拥塞控制 🔥🔥 如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。