转载自 cyc2018
三次握手
三次握手过程
- B 处于 LISTEN(监听)状态,等待来自 A 的连接请求。
- A 向 B 发送连接请求报文 SYN。
- B 收到 A 发来的 SYN,如果同意建立连接,则向 A 发送连接确认报文 SYN ACK。
- A 收到 SYN ACK 后,还要向 B 发出确认报文 ACK。
- B 收到 ACK 后,连接建立。
应该注意到,接收了 SYN 之后的所有报文都存在 ACK 字段。
三次握手的原因
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
四次挥手
四次挥手过程
- A 发送连接释放报文 FIN。
- B 收到 FIN 之后发出确认 ACK,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据。
- 当 B 不再需要连接时,发送连接释放报文 FIN。
- A 收到 FIN 后发出确认 ACK,进入 TIME-WAIT 状态,等待 2 倍的 MSL(最大报文存活时间)后释放连接。
- B 收到 ACK 后释放连接。
四次挥手的原因
客户端发送了 FIN 连接释放报文之后,服务器端收到了这个报文,就进入了 CLOSE-WAIT 状态。这个状态是为了让服务器端发送还未传送完毕的数据,传送完毕之后,服务器端会发送 FIN 连接释放报文。
TIME_WAIT
客户端接收到服务器端的 FIN 报文后进入此状态,而并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间 2MSL。这么做有两个理由:
- 确保最后一个确认报文 ACK 能够到达。如果服务器端没收到客户端发送来的确认报文 ACK,那么就需要重新发送连接释放请求报文 FIN,客户端等待一段时间就是为了处理这种情况的发生。
- 等待一段时间是为了让本次连接持续时间内产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文 SYN,从而错误打开连接。
抓包演示
使用 Wireshark 进行抓包,最开始使用 tcp 过滤器来进行观察,得到想要分析的 ip 地址 223.111.209.218。
之后再使用这个 ip 地址作为源地址和目的地址过滤器。
ip.src223.111.209.218 or ip.dst223.111.209.218
观察到下面的四个包,分别表示:
- 192.168.199.141 发出 SYN 连接请求报文 ;
- 223.111.209.218 接收到连接请求之后返回 SYN ACK 确认报文;
- 192.168.199.141 进行最后确认返回 ACK 报文;
- 192.168.199.141 发起 HTTP GET 请求。
(注:以下抓包结果进行了过滤,所以序号 Seq 和确认号 Ack 不连续。)
再观察到以下五个包,分别表示:
192.168.199.141 发出连接释放报文 FIN ACK;
223.111.209.218 返回 ACK 确认报文;
此时 TCP 处于半关闭状态,223.111.209.218 继续发送还未发送完的 HTTP 响应报文;
223.111.209.218 不再需要发送数据之后,发出连接释放报文 FIN ACK;
192.168.199.141 最后确认,返回 ACK 报文。