说明
- SYN=1 的报文段不能携带数据,但是要消耗 1 个序号。
- FIN=1 的报文段即使不携带数据,也要消耗 1 个序号。
- ACK报文段可以携带数据,不携带数据不消耗序号。
连接的建立 - 三次握手(three-way handshake)
- client 向 server发起连接请求报文,设置 SYN=1,seq = x。状态 CLOSED -> SYN_SENT
- server 收到请求同意连接发出确认报文 SYN=1,ACK=1,ack = x+1,seq = y。状态 LISTEN -> SYN-RCVD
- client 收到请求发出确认 ACK=1,ack = y+1,seq = x+1。状态 SYN-SENT -> ESTABLISHED 。server 收到确认。状态 SYN-RCVD -> ESTABLISHED
连接的释放 - 四次握手。
任何一方都可以主动关闭。
- client主动关闭,发出关闭请求 FIN=1,seq = u。状态 ESTABLISHED -> FIN-WAIT-1
- server收到,发出确认 ACK=1,ack = u+1,seq = v。状态 ESTABLISHED -> CLOSE-WAIT,client 收到确认。状态 FIN-WAIT-1 -> FIN-WAIT-2
此时 client到server的连接关闭了,client没有数据要发给server了。server可能还有数据要发给client
- server发出连接释放请求 FIN=1,ACK=1,ack = u+1,seq = w,状态 CLOSE-WAIT -> LAST-ACK。
- client收到,发出确认 ACK=1,ack = w+1,seq = u+1。状态 FIN-WAIT-2 -> TIME-WAIT。server收到,关闭连接进入 CLOSED状态。
此时server已经关闭了,客户端还需要等待 2MSL 的时间才可以关闭。
- MSL 叫做最长报文段寿命(Maximum Segment Lifetime)
RFC 793建议设置2分钟,对现在的网络来说太长了。
client为什么要等2MSL的时间呢,有两方面考虑。
-
主要是考虑到server可能没有收到client最后发出的确认。所以先等等,如果client最后的确认丢失了。server收不到最后的请求,就会以为自己发出的释放连接请求client没有收到,所以就会重传连接释放请求报文。此时client收到server重传的释放连接请求报文,就会重新发出最后的确认。然后重新设置等待关闭的时间为 2MSL。
-
可能client发出的报文还在网络的某处滞留,直接关闭然后发出新的请求,可以会出现无效的连接请求。经过2MSL时间后可以保证之前发出的报文在网络中消失。
TCP还设有一个保活计时器(keepalive timer)
- 主要考虑到客户端由于死机断电等一些情况导致的TCP连接不能正常释放。
- 服务端设置保活计时器。当一段时间没有收到客户端的报文时,就会发出一个探测报文。
- 一般是2个小时以后,之后每75秒发送一次。发送10次后依然没有收到客户端的相应。客户端就就关闭TCP连接。