当我们向服务器发送HTTP请求,获取数据、修改信息时,都要建立TCP连接,包括三次握手,四次挥手。
什么是TCP连接?
为了实现可靠的数据传输,TCP要在应用进程之间建立传输连接。它是在两个传输用户之间建立一种逻辑联系,使得通信双方都确认对方为自己的传输端点。
建立连接:
建立连接前,服务器端首先被动打开其熟知的端口,对端口进行监听。当客户端要和服务器端建立连接时,发起一个主动打开端口的请求,该端口一般为临时端口,然后进入三次握手的过程:
三次握手:
设主机B运行一个服务器进程,它先发出一个被动打开命令,告诉它的TCP要准备接收客户进程的连续请求,然后服务进程就处于听的状态。不断检测是否有客户进程发起连续请求,如有,作出响应。设客户进程运行在主机A中,他先向自己的TCP发出主动打开的命令,表明要向某个IP地址的某个端口建立运输连接,过程如下:
1)主机A的TCP向主机B的TCP发出连接请求报文段,其首部中的同步比特SYN应置1,同时选择一个序号x,表明在后面传送数据时的第一个数据字节的序号是x。
2)主机B的TCP收到连接请求报文段后,如同意,则发挥确认。在确认报文段中应将SYN置为1,确认号应为x+1,同时也为自己选择一个序号y
3)主机A的TCP收到此报文段后,还要向B给出确认,其确认号为y+1
4)主机A的TCP通知上层应用进程,连接已经建立,当主机B的TCP收到主机A的确认后,也通知上层应用进程,连接建立。
连接释放
在数据传输完毕之后,通信双方都可以发出释放连接的请求。释放连接的过程为如上图所示:
1)数据传输结束后,主机A的应用进程先向其TCP发出释放连接请求,不在发送数据。TCP通知对方要释放从A到B的连接,将发往主机B的TCP报文段首部的终止比特FIN置为1,序号u等于已传送数据的最后一个字节的序号加1。
2)主机B的TCP收到释放连接通知后发出确认,其序号为u+1,同时通知应用进程,这样A到B的连接就释放了,连接处于半关闭状态。主机B不在接受主机A发来的数据;但主机B还向A发送数据,主机A若正确接收数据仍需要发送确认。
3)在主机B向主机A的数据发送结束后,其应用进程就通知TCP释放连接。主机B发出的连接释放报文段必须将终止比特置为1,并使其序号w等于前面已经传送过的数据的最后一个字节的序号加 1,还必须重复上次已发送过的ACK=u+1。
4)主机A对主机B的连接释放报文段发出确认,将ACK置为1,ACK=w+1, seq=u+1。这样才把从B到A的反方向连接释放掉,主机A的TCP再向其应用进程报告,整个连接已经全部释放。
注意的问题:
- 三次握手建立连接时,发送方再次发送确认的必要性
-
- 主要是为了防止已失效的连接请求报文段突然又传到了B,因而产生错误。假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达B,本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了,这样一直等待A发来数据,B的许多资源就这样白白浪费了。
- TIME_WAIT状态:
首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就是说该发送方会保持2MSL时间之后才会回到初始状态。MSL指的是数据包在网络中的最大生存时间。产生这种结果使得这个TCP连接在2MSL连接等待期间,定义这个连接的四元组(客户端IP地址和端口,服务器IP地址和端口)不能被使用。
产生原因:
- 为了实现TCP全双工连接的可靠释放;假设发起主动关闭的一方(client)最后发送的ACK在网络中丢失,由于TCP协议的重传机制,执行被动关闭的一方将会重新发送FIN,在该FIN到达client之前,client必须维护这条连接状态,也就是说TCP连接对应的资源不能被立即释放或者重新分配,直到另一方重发的FIN到达后,client重发ACK后,经过2MSL时间周期没有再收到另一方的FIN之后,该TCP连接才能恢复初始的CLOSED状态。如果主动关闭方不维护这样一个TIME_WAIT状态,那么当被动关闭一方重发的FIN到达时,主动关闭一方的TCP传输层会用RST包响应对方,这会被对方认为是有错误发生,然而这事实上只是正常的关闭连接过程,并非异常;
- 为使旧的数据包在网络中因过期而消失。
- 四次挥手释放连接时,等待2MSL的意义
-
- 第一,为了保证A发送的最有一个ACK报文段能够到达B。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的B收不到对已发送的FIN和ACK报文段的确认。B会超时重传这个FIN和ACK报文段,而A就能在2MSL时间内收到这个重传的ACK+FIN报文段。接着A重传一次确认。
- 第二,就是防止上面提到的已失效的连接请求报文段出现在本连接中,A在发送完最有一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。
TCP的有限状态机
CLOSED:关闭状态,没有连接活动或正在进行。
LISTEN:表示服务器端的某个socket处于监听状态,正在等待连接进入。
SYN-SENT:已经发出连接请求,等待确认。
SYN-RCVD:收到一个连接请求,尚未确认。
ESTABLISHED:连接建立,正常数据传输状态。
FIN-WAIT-1:(主动关闭)已经发送关闭请求,等待确认。
FIN-WAIT-2:(主动关闭)收到对方关闭确认,等待对方关闭请求。
TIME-WAIT:完成双向关闭,等待所有分组死掉。表示收到了对方的FIN报文,并发出ACK报文,等待2MSL后即可回到CLOSED可用状态了。如果FIN-WAIT-1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME-WAIT状态,无需经过FIN-WAIT-2状态。
CLOSING:双方同时尝试关闭,等待对方确认,比较少见。
CLOSE-WAIT:(被动关闭)收到对方关闭请求,已经确认。需要查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个socket,发送FIN给对方,也就是关闭连接。
LAST-ACK:(被动关闭)等待最后一个关闭确认,并等待所有分组死掉。它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也就可以进入到CLOSED可用状态了。