一、字段说明:
字段: | 含义: |
---|---|
SYN,seq | 同步报文段 |
ACK,ack | 确认报文段 |
ack | 确认号 |
seq | 序列号 |
SYN | 同步位 |
FIN | 终止位 |
ACK | 确认位 |
二、三次握手:
第一次: 连接请求报文段: SYN=1(请求连接) 初始序号seq=x(客户端初始序号)
第二次: 确认报文段(同意连接): SYN =1(请求连接) seq= y(服务器自己的初始序号) ACK = 1(确认收到) ack = x+1(确认号)
第三次: 确认报文段:ACK=1(确认收到) seq=x+1 (客户端序号) ack=y+1(确认号) 确认号ack是上一次的序号seq加1
总结: ack的值等于对方上一次发送的报文段中的seq的值加一,
seq的值等于自己上一次发送的报文段中的seq的值加一(第一次seq值任意取)
简图:
- B 处于 LISTEN(监听)状态,等待来自 A 的连接请求。
- A 向 B 发送连接请求报文 SYN。
- B 收到 A 发来的 SYN,如果同意建立连接,则向 A 发送连接确认报文 SYN ACK。
- A 收到 SYN ACK 后,还要向 B 发出确认报文 ACK。
- B 收到 ACK 后,连接建立。
应该注意到,接收了 SYN 之后的所有报文都存在 ACK 字段。
三、三次握手的原因:
第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
客户端发送的连接请求如果在网络中滞留,那么就会隔很长一段时间才能收到服务器端发回的连接确认。客户端等待一个超时重传时间之后,就会重新请求连接。但是这个滞留的连接请求最后还是会到达服务器,如果不进行三次握手,那么服务器就会打开两个连接。如果有第三次握手,客户端会忽略服务器之后发送的对滞留连接请求的连接确认,不进行第三次握手,因此就不会再次打开连接。
四、四次挥手:
简图:
第一次: 连接释放报文段: FIN=1 seq=u(u为前面已经传送过的数据的最后一个字节的序号加一)
第二次: 连接释放确认报文段: 确认只断开A—B ACK= 1(确认收到) ack=u+1(确认号) seq=v(v为为前面已经传送过的数据的最后一个字节的序号加一)
第三次: 连接释放确认报文段: 断开B----A FIN = 1 ACK =1 ack=u+1 seq=w(seq=v后还发送了数据, w是前面已经传送过的数据的最后一个字节的序号加一)
第四次: 连接释放确认报文段 : 确认断开B—A ACK=1 ack = w+1 seq=u+1
- 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,从而错误打开连接。