TCP的建立连接:
TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段。如图:
假定A运行的是客户端程序,B运行的是服务器程序。最初TCP两端都处于CLOSED(关闭)状态。图中各方框为TCP进程的各个状态。在本例中A为主动打开,B为被动打开.
一开始服务器B初始化TCB模块并进入LISTEN状态。等待A发出连接请求,如有则发出响应。
A的TCP客户进程主动打开初始化TCB模块并发送报文:SYN=1,seq = x(同步SYN= 1 ,确认ACK =0.为请求连接。若对方同意则回复报文:SYN = 1,ACK = 1;同时消耗一个有一个序列号x 。该报文不携带数据)并进入SYN-SENT(同步已发送)状态。
B客户进程接受到该报文后同意建立连接将ACK置1、消耗一个序号y、回复确认序列号x+1、发送报文:SYN =1,ACK= 1,seq= x+1,seq=y ;该报文也不能携带数据;并进入SYN-RCVD(同步已收到)状态。
A的TCP客户端收到B的确认后,还要向B给出确认。确认报文段ACK置1,确认号seq = y+1,而自己的序列号seq = x+1。发送报文:ACK = 1,seq = x+1,seq=y+1。
并进入ESTAB-LISHED(已建立连接)状态。TCP标准规定,ACK报文段可携带数据,但是如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍然是seq=x+1。
B收到A的确认后,也进入ESTAB-LISHED状态。
关于TCP建立连接为什么是三报文握手而不是两报文握手(A还要发送确认)。其实其实是为了为了防止已失效的报文段突然又传送到了B,因而产生错误。
TCP连接的释放:
现在A,B都处于ESTAB-LISHED状态,A向其TCP发送连接释放报文段:FIN =1,seq=u(u发送过数据最一个字节的序号加一)。此时A主动关闭连接,停止发送数据进入FIN-WAIT-1(终止等待1)状态。等待B的确认,TCP规定,FIN报文段不能携带数据,同时消耗一个序号(u)。
B收到A发来的报文后即发出确认报文:ACK=1,seq = u+1,seq= v。然后进入CLOSE-WAIT(关闭等待状态)。TCP服务器应用进程通知层应用进程,A到B这个方向的连接就释放了。此时TCP就处于半关闭(half-close)状态。即A无数据要发送了,但B若有数据要发送,A仍然要接收(B到A这个方向仍然没有关闭)。这个状态仍然会持续一段时间。
A收到B确认后,就进入FIN-WAIT2(终止等待2)状态,等待B发来;连接释放报文段。
若B无数据要向A重复上次的发送报文:FIN=1,ACK=1,seq=w,seq=u+1。(其中序号w,中断A到B方向的连接后可能B向A发送了数据同理w为最后一个字节序号加一,同时为中断报文FIN置1)B进入LAST-ACK(最后确认)状态。等待A的确认。
A收到B的连接释放报文以后,向B发出确认报文:ACK=1,seq = u+1,seq= w+1。发送以后A进入TIME-WAIT(时间等待)状态。时间等待计时器经过两个XML(最长报文段寿命,一般XML=2分钟,同时TCP允许对特殊情况使用更小的XML值)
上述的TCP连接释放过程是四报文握手。
除此之外,TCP还设有一个保活计时器。用来应对客户进程突发故障不能工作的情况。