第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
TCP Client
|
Flags
|
TCP Server
|
1 Send SYN (seq=x)
|
----SYN--->
|
SYN Received
|
2 SYN/ACK Received
|
<---SYN/ACK----
|
Send SYN (seq=y), ACK (x+1)
|
3 Send ACK (y+1)
|
----ACK--->
|
ACK Received, Connection Established
|
w: ISN (Initial Sequence Number) of the Client
| ||
x: ISN of the Server
|
TCP报文主要有序号、确认序号、URG、ACK、RSH、RST、SYN、FIN、检验和、紧急数据指针等构成。连接过程中,ACK、RSH、RST、SYN、FIN这些标志位起到决定作用。
SYN:该标志位用来建立连接,让连接双方同步序列号,如果SYN=1,ACK=0,表示该数据包为连接请求;若SYN=1,ACK=1,则表示接受连接。
FIN:表示发送端没有数据传输了,要求释放连接。
RST:复位一个连接。
URG:紧急数据标志,若为1,表示包中含有紧急数据,此时紧急数据指针有效。
ACK:确认标志位,若为1,表示包中的确认号是有效的,否则包中的确认号无效。
PSH:如果置位,接收端应尽快把数据传送给应用层。
连接撤销过程中,有如下过程:
1.HOST1上的应用程序关闭己方的连接导致TCP发送一个FIN消息给HOST2。
2.HOST2发送一个确认消息给HOST1,并且HOST2把FIN作为EOF递交给HOST2上的应用程序。
3.一段时间过后,HOST2上的应用程序关闭它那边的连接,引发一个FIN消息给HOST1。
4.HOST1给HOST2发送一个确认消息,然后HOST2关闭连接并释放资源,然而,HOST1却没有关闭连接,而是进入了TIME_WAIT状态,并为两个最大段生存时间(2MSL)保留在此状态.
:
为什么需要TIME_WAIT?
1.因为在第四步的时候,HOST1发送的ACK可能丢失并导致HOST2重新发送FIN消息,TIME_WAIT维护连接状态.
如果执行主动关闭的一方HOST1 不进入到TIME_WAIT状态就关闭连接那会发生什么呢?当重传的FIN消息到达时,因为TCP已经不再有连接的信息了,所以就用RST(重新启动)消息应答,导致HOST2进入错误的状态而不是有序终止状态,如果发送最后ACK消息的一方处于TIME_WAIT状态并仍然记录着连接的信息,它就可以正确的响应对等方HOST2的FIN消息了.
2.TIME_WAIT为连接中”离群的段”提供从网络中消失的时间.
考虑一下,如果延迟或者重传段在连接关闭后到达时会发生什么呢?通常情况下,因为TCP仅仅丢弃该数据并响应RST消息,所以这不会造成任何问题。当RST消息到达发出延时段的主机时,因为该主机也没有记录连接的任何信息,所以它也丢弃该段。然而,如果两个相同主机之间又建立了一个具有相同端口号的新连接,那么离群的段就可能被看成是新连接的,如果离群的段中数据的任何序列号恰恰在新连接的当前接收窗口中,数据就会被重新接收,其结果就是破坏新连接。