TCP状态
TCP三次握手状态
在TCP的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:
未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于 Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器也进入ESTABLISHED状态
在断开时:1. 主动方发出设置了FIN位的报文,表示主动终止从本地到远端的单向连接;
此时,主动方进入FIN_WAIT1状态,意思就是它在等待远端的FIN报文;
2. 远端收到FIN后,会立即发送ACK;主动方收到ACK后,进入FIN WAIT2状态,所以FIN-WAIT1状态持续的非常短;
此时远端进入CLOSE-WAIT状态,一条单向连接终止了,但另一条还没有,处于HALF-CLOSE连接状态;
3.当远端进行了必要的数据发送后,它发送FIN,表示从它出发的单向连接也要关闭;同时它进入LAST ACK状态;
4.主动方收到FIN后,回应一个ACK;远端就此进入CLOSED状态,连接关闭;
5.主动方进入TIME WAIT状态;确保最后一个ACK没有丢失,防止新连接占用刚刚关闭的主动方的地址端口,使得网络中流浪的老连接的分组被误认为新连接的分组。
补概念:
半开连接:一方已经关闭或异常终止连接,但另一方却不知道。比如某端突然断电了,另一端是无法感知的。
1,只要TCP的缓冲里还有未读取(read)数据,则调用close时会直接向对端发送RST。
2,shutdown与socket描述符没有关系,即使调用shutdown(fd, SHUT_RDWR)也不会关闭fd,最终还需close(fd)。
3,在已发送FIN包后write该socket描述符会引发EPIPE/SIGPIPE。
4,当有多个socket描述符指向同一socket对象时,调用close时首先会递减该对象的引用计数,计数为0时才会发送FIN包结束TCP连接。shutdown不同,只要以SHUT_WR/SHUT_RDWR方式调用即发送FIN包。
5,SO_LINGER与close,当SO_LINGER选项开启但超时值为0时,调用close直接发送RST(这样可以避免进入TIME_WAIT状态,但破坏了TCP协议的正常工作方式),SO_LINGER对shutdown无影响。
6,TCP连接上出现RST与随后可能的TIME_WAIT状态没有直接关系,主动发FIN包方必然会进入TIME_WAIT状态,除非不发送FIN而直接以发送RST结束连接
TCP连接状态和说明:
状态 |
说明 |
CLOSED |
不存在TCP连接 |
LISTEN |
一个应用层协议已经发布了一个被动打开,并且有意接收TCP连接企图 |
SYN SENT |
一个应用层协议已经发布一个主动打开,并且发送一个SYN段 |
SYN RCVD |
一个SYN段被接收,并且一个SYN-ACK被发送 |
ESTABLISHED |
建立TCP连接的3此握手完成。现在数据能双向传输 |
FIN WAIT-1 |
初始的关闭连接段的FIN-ACK被发送 |
FIN WAIT-2 |
响应初始的FIN-ACK的ACK被接收 |
CLOSING |
一个FIN-ACK被接收但ACK不是针对已发送的FIN-ACK的。收到的FIN-ACK中的是针对已发送的FINA-ACK被称为同时关闭,这时两个TCP对等端在相同时刻发送FIN-ACK。 |
TIME WAIT |
FIN- ACK已被发送并得到两个对等端的确认,并且TCP连接终止进程完成。一旦到达TIME WAIT状态,在连接的TCP端口能被重新使用前,TCP必须等待的时间是最大生存时间(MSL)的两倍。MSL是在互联网中一个TCP段能存在时间的最 大值,推荐是240秒。这个延迟防止一个使用相同端口的连接的TCP段与旧连接的TCP段的副本相混淆 |
CLOSE WAIT |
一个FIN-ACK被接收,并且一个FIN-ACK被发送 |
LAST ACK |
响应FIN-ACK的ACK已被接收 |