计算机网络传输层详解
传输层
一、TCP 三次握手(以SOCKET的角度)
二、TCP 四次挥手

- TIME_WAIT 状态的产生
该状态出现在主动断开方,在主动断开方完成第四次挥手,也就是发送完最后一个ACK报文后,进入 TIME_WAIT 状态,该状态会持续 2MSL 的时长,以确保对方已收到了最后一个ACK报文。
- **MSL:**最大报文存活时长,单位是时间,Linux默认 30s。
- **TTL:**IP报文在网络中允许经过的最大路由数,单位是经过路由数,Linux默认64。
- TIME_WAIT 为什么要等待 2MSL
2 MSL的时长,相当于:允许报文在网络中丢失一次。
比如:第四挥手ACK报文没有被被动方接收到,1个MSL后该ACK报文在网路中消亡,被动方由于没有收到ACK响应,会启动FIN报文重传,另一方接收到FIN报文,就可以重发ACK报文。这样的一来一回正是 2MSL时长内。
- TIME_WAIT 过多的危害
在Linux中,某种东西过多一般会意味着:占用系统资源。文件描述符、内存资源、CPU资源等等。
TIME_WAIT 过多的时候,由于与网络有关,所以会有以下两个基本的影响:
- 占用系统资源,一切皆文件,会占用较多的文件描述符、内存资源。
- 占用系统端口,端口资源是有限的,linux一般可以开启的端口为 3w-6w。
在以上基本影响外,客户端和服务端的 TIME_WAIT 过多的影响也有不同:
客户端:TCP四元组确定一条连接,所以不能对 目的IP+目的port 相同的服务端发起连接请求,端口耗尽。
服务端:由于TCP四元组确定一条连接,所以服务端可以处理的TCP连接理论上可以非常多,但是TCP连接在服务端会受限于系统资源,文件描述符和内存资源
TIME_WAIT 过多如何解决
- **客户端:**可以考虑开启 tcp_tw_reuse 参数,设置为1为开启。当发起新连接的时候,就会复用处于 time_wait的连接。
- 启用后,处于 TIME-WAIT 状态的连接可能被重用。这种重用可能导致新的连接混淆,因为内核会重用一个旧连接的五元组(源 IP、源端口、目的 IP、目的端口和协议),这可能导致数据包被误导。
- **服务端:**说明服务端主动关闭了连接,服务端应该尽量避免主动断开连接,由客户端来进行,可以在应用层设计一个逻辑,当服务端要断开的时候,发送一个消息给客户端,让客户端收到信息后发起断开TCP连接。
- TIME_WAIT 在服务端大量出现的原因?
相当于: 服务端为什么会主动关闭连接?
**没有开启HTTP长连接:**服务端发完HTTP响应后,会主动关闭连接。
**HTTP长连接的请求数量设置过小:**web服务端通常会有个参数来定义 HTTP 长连接能处理的最大请求数量,比如 nginx的 keepalive_requests默认是100。QPS高的时候,就会频繁关闭连接,导致time_wait过多。
TIME_WAIT 状态设计的目的
设计 TIME_WAIT 状态,主要有两个原因:
- 防止历史连接中的数据,被后面相同四元组的连接错误的接收(序列号是32位,可能会有序列号绕回导致数据完整性破坏);
- 保证「被动关闭连接」的一方,能被正确的关闭(确保有没有收到最后一次挥手);
假设 TCP 的发送窗口是 1 GB,并且使用了时间戳选项,发送方会为每个 TCP 报文分配时间戳数值,我们假设每个报文时间加 1,然后使用这个连接传输一个 6GB 大小的数据流。

32 位的序列号(2^32 = 4 GB)在时刻 D 和 E 之间回绕。假设在时刻B有一个报文丢失并被重传,又假设这个报文段在网络上绕了远路并在时刻 F 重新出现。如果 TCP 无法识别这个绕回的报文,那么数据完整性就会遭到破坏。
- TCP_TW_REUSE 为什么默认关闭
- 开启 tcp_tw_reuse 的同时,也需要开启tcp_timestamps。
- 开启了 tcp_timestamps参数,TCP 头部就会使用时间戳选项,它有两个好处,一个是便于精确计算 RTT ,另一个是能防止序列号回绕(PAWS)。
默认关闭的原因:
启用后,处于 TIME-WAIT 状态的连接可能被重用。这种重用可能导致新的连接混淆,因为内核会重用一个旧连接的五元组(源 IP、源端口、目的 IP、目的端口和协议),这可能导致数据包被误导。
三、TCP长连接、HTTP长连接 的保活机制
- **TCP长连接保活:**通过探测报文来检测连接状态。这是传输层的机制,独立于应用层的具体协议。
- **HTTP长连接保活:**通过Connection: keep-alive和Keep-Alive头部字段来管理连接的持久性和空闲超时。
Connection: keep-alive
Keep-Alive: timeout=5, max=100HTTP长连接的保活实际上是由两部分组成的:应用层的HTTP保活机制和传输层的TCP保活机制。
- HTTP保活负责管理HTTP请求/响应的连接复用和空闲超时
- TCP保活负责确保底层连接的持续有效性。如果TCP连接因任何原因断开,HTTP长连接也会失效。
三、socket 五元组
- 源IP地址
- 目的IP地址
- 源端口号
- 目的端口号
- 传输协议(通常是TCP或UDP)
常说的TCP四元组,是指默认 传输协议固定为TCP的情况下讨论的。
也可以得出,tcp/udp可以使用同一个端口。因为传输协议不同,不会认为是相同的连接。
四、传输层的报文
- 端口
tcp和udp都有端口字段,用于区分同一主机的不同应用程序的数据包。