一、TCP的三次握手
握手之前的准备
- 服务器:被动打开过程。socket--bind--listen
- 客户端:主动打开过程。socket
三次握手的描述:
- 第一步:客户端调用connect发起主动连接。这导致客户端TCP发送一个SYN分节,他告诉服务器将在待建立的连接中发送的数据的初始序列号。通常SYN不携带任何数据,其所在的IP数据包只有一个IP首部,一个TCP首部,以及可能的TCP选项。
- 第二步:服务器必须确认(ACK)客户端的SYN,同时自己也要发送一个SYN分节,他包含服务器将在同一连接中发送的数据的初始序列号和对客户SYN确认的确认号。确认号等于上一个SYN+1,SYN大小是一个字节。
- 第三步:客户端确认服务器的SYN.(即向服务器发送确认号)。
二、四次挥手(关闭链接可以有任意一方)
- 第一步:某个应用进程调用close,该端执行主动关闭,于是该端发送一个FIN分节,表示数据发送完毕
- 第二步:接收这个FIN分节的这一端执行被动关闭,这个FIN由TCP确认,他的接收也作为一个文件描述符传递给接收端应用程序,放在排队等候改应用进程接收的任何其他数据之后。
- 第三步:一段时间后,接收到这个文件描述符的应用进程调用close关闭套接字,这导致他的TCP也发送一个FIN
- 第四步:接收这个最终FIN的原发送端TCP(执行主动关闭的那一端)确认这个FIN
三、TCP的状态转换图
- 1.CLOSED:起始点,在超时或者连接关闭时候进入此状态。
- 2.LISTEN:服务端在等待连接过来时候的状态,服务端为此要调用socket,bind,listen函数,就能进入此状态。此称为应用程序被动打开(等待客户端来连接)。
- 3.SYN_SENT:客户端发起连接,发送SYN给服务器端。如果服务器端不能连接,则直接进入CLOSED状态。
- 4.SYN_RCVD:跟3对应,服务器端接受客户端的SYN请求,服务器端由LISTEN状态进入SYN_RCVD状态。同时服务器端要回应一个ACK,同时发送一个SYN给客户端;另外一种情况,客户端在发起SYN的同时接收到服务器端得SYN请求,客户端就会由SYN_SENT到SYN_RCVD状态。
- 5.ESTABLISHED:服务器端和客户端在完成3次握手进入状态,说明已经可以开始传输数据了。
- 以上是建立连接时服务器端和客户端产生的状态转移说明。相对来说比较简单明了,如果你对三次握手比较熟悉,建立连接时的状态转移还是很容易理解。
- 下面,我们来看看连接关闭时候的状态转移说明,关闭需要进行4次双方的交互,还包括要处理一些善后工作(TIME_WAIT状态),注意,这里主动关闭的一方或被动关闭的一方不是指特指服务器端或者客户端,是相对于谁先发起关闭请求来说的:
- 6.FIN_WAIT_1:主动关闭的一方,由状态5进入此状态。具体的动作是发送FIN给对方。
- 7.FIN_WAIT_2:主动关闭的一方,接收到对方的FIN-ACK(即fin包的回应包),进入此状态。
- 8.CLOSE_WAIT:接收到FIN以后,被动关闭的一方进入此状态。具体动作是接收到FIN,同时发送ACK。(之所以叫close_wait可以理解为被动关闭方此时正在等待上层应用发出关闭连接指令)
- 9.LAST_ACK:被动关闭的一方,发起关闭请求,由状态8进入此状态。具体动作是发送FIN给对方,同时在接收到ACK时进入CLOSED状态。
- 10.CLOSING:两边同时发起关闭请求时,会由FIN_WAIT_1进入此状态。具体动作是接收到FIN请求,同时响应一个ACK。
- 11.TIME_WAIT:从状态图上可以看出,有3个状态可以转化成它
a.由FIN_WAIT_2进入此状态:在双方不同时发起FIN的情况下,主动关闭的一方在完成自身发起的关闭请求后,接收到被动关闭一方的FIN后进入的状态。
b.由CLOSING状态进入:双方同时发起关闭,都做了发起FIN的请求,同时接收到了FIN并做了ACK的情况下,由CLOSING状态进入。
c.由FIN_WAIT_1状态进入:同时接受到FIN(对方发起),ACK(本身发起的FIN回应),与b的区别在于本身发起的FIN回应的ACK先于对方的FIN请求到达,而b是FIN先到达。这种情况概率最小。
关闭的4次连接最难理解的状态是TIME_WAIT,存在TIME_WAIT的2个理由:
1.可靠地实现TCP全双工连接的终止。
2.允许老的重复分节在网络中消逝。
四、完整的例子
图片来源于快课网