1. 连接步骤
1.1. 建立连接
3 次握手
- Server 端建立连接前需要监听端口, 处于 LISTEN 状态.
- Client 端准备建立连接, 先发送一个 SYN 同步包给 Server 端, Client 端进入 SYN_SENT 状态.
- Server 端收到 SYN 后, 同意建立连接, 向 Client 端回复一个 ACK. 由于 TCP 是双工传输, Server 端也会同时向 Client 端发送一个 SYN, 申请 Server 向 Client 方向建立连接. 发送完 ACK 和 SYN 后, Server 端进入 SYN_RCVD 状态.
- Client 端收到 Server 端的 ACK 后, Client 端进入 ESTABLISHED 状态; 同时 Client 端 向 Server 端发送 ACK, 回复 Server 端的 SYN 请求.
- Server 端收到 Client 端的 ACK 后, Server 端也进入 ESTABLISHED 状态. 此时建连完成, 双方随时可以进行数据传输.
1.1.1. 为什么需要 3 次握手?
为了防止已失效的连接请求报文段突然又传送到了服务端导致错误.
在双方的 SYN 包中都会包含一个 随机序号, 在 ACK 应答时必须返回 随机序号 + 1.
1.1.2. 如何防御 SYN 洪水攻击?
SYN 洪水攻击的原因是 Server 端收到 Client 端的 SYN 请求后, 发送 ACK 和 SYN, 但是 Client 端不进行回复, 导致 Server 端大量的连接处于 SYN_RCVD 状态, 进而影响其他aggie请求的建连.
可以设置 tcp_synack_retries = 0 加快半连接的回收速度, 或者调大 tcp_max_syn_backlog 来应对大量的 SYN 洪水攻击.
1.2. 关闭连接
4 次挥手
- Client 端和 Server 端都是 ESTABLISHED 状态. 此时双方都可以发起关闭连接, 暂且把先发起的一方看做 Client 端.
- Client 端向 Server 端发送 FIN 包, 表示 Client 端已经没有数据要发送了, 然后 Client 端进入 FIN_WAIT_1 状态.
- Server 端收到 FIN 后, 返回 ACK, 然后进入 CLOSE_WAIT 状态, 而 Client 端接收到 ACK 后进入 FIN_WAIT_2 状态. 此时 Server 端属于半关闭状态, 因为此时 Client 端向 Server 端方向已经不会发送数据了, 可是 Server 端可能还有数据要发送.
- 当 Server 端发送完毕后, 向 Client 端发送 FIN, 表示 Server 端也没有数据发送了, 此时 Server 端进入 LAST_ACK 状态, 就等待 Client 端的应答就可以关闭连接了.
- Client 端收到 Server 端的 FIN 包后, 回复 ACK, 然后进入 TIME_WAIT 状态. Server 端接收到 ACK 后直接进入 CLOSED 状态. 而 Client 端在 TIME_WAIT 状态下需要等待 2 倍的最大报文段生存时间, 来保证连接的可靠关闭, 之后才会进入 CLOSED 状态.
1.2.1. 为什么 Client 端需要等待 2 倍的最大报文段生存时间之后才关闭连接?
- 保证 TCP 协议的全双工连接能够可靠关闭.
- 保证这次连接的重复数据段从网络中消失, 防止端口被重用时可能产生数据混淆.
1.2.2. 为什么需要 4 次挥手?
为了确认双方都没有数据发送.
2. 滑动窗口
// todo 2020-07-19
3. 拥塞控制
// todo 2020-07-19
4. Nagel 算法和 ACK 延迟
// todo 2020-07-19