TCP三次握手和四次挥手,及TCP协议端口状态说明:CLOSE-WAIT、TIME-WAIT 、LISTENING、SYN_SENT、ESTABLISHED、LAST-ACK ...

TCP三次握手和四次挥手,及TCP协议端口状态说明:CLOSE-WAIT、TIME-WAIT 、LISTENING、SYN_SENT、ESTABLISHED、LAST-ACK ...

2018年09月13日 18:10:56 a3192048 阅读数:149

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(TCP连接成功)状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。

 

四次挥手:

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
(1) TCP客户端发送一个FIN,用来关闭客户到服务器的数据传送。
(2) 服务器收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3) 服务器关闭客户端的连接,发送一个FIN给客户端。
(4) 客户端发回ACK报文确认,并将确认序号设置为收到序号加1。

 

CLOSED:
这个没什么好说的了,表示初始状态。


LISTENING(服务端状态):
这个也是非常容易理解的一个状态,表示服务器端的某个SOCKET处于监听状态,可以接受连接了。也即提供某种服务,侦听远方TCP端口的连接请求,当提供的服务没有被连接时,处于LISTENING状态,端口是开放的,等待被连接。


SYN_RCVD (服务端状态):
这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。


SYN_SENT(客户端状态):
这个状态与SYN_RCVD遥相呼应,当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。SYN_SENT状态表示客户端已发送SYN报文。


ESTABLISHED:
这个容易理解了,表示连接已经建立了。


FIN_WAIT_1(客户端状态):
这个状态要好好解释一下,其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义都是表示等待对方的FIN报文。而这两种状态的区别是:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。


FIN_WAIT_2(客户端状态):
上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。从远程TCP等待连接中断请求,主动关闭端接到ACK后,就进入了FIN-WAIT-2 .这是在关闭连接时,客户端和服务器两次握手之后的状态,是著名的半关闭的状态了,在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于FIN_WAIT_2状态,而服务器则一直处于WAIT_CLOSE状态,而直到应用层来决定关闭这个状态。

 


TIME_WAIT(客户端状态):
表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

注:MSL(Maximum Segment Lifetime):即报文段最大生存时间。

为什么客户端在TIME-WAIT状态必须等待2MSL时间呢? 
第一,为了保证客户端发送的最后一个ACK报文能够到达服务端。这个ACK报文段有可能丢失,因而使处在LAST-ACK状态的服务端收不到对已发送的FIN+ACK报文段的确认。服务端会超时重传这个FIN+ACK报文段,而客户端就能在2MSL时间内收到这个重传的FIN+ACK报文段。如果客户端在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后就立即释放连接,就无法收到服务端重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,服务端就无法按照正常的步骤进入CLOSED状态。 
第二,客户端在发送完ACK报文段后,再经过2MSL时间,就可以使本连接持续的时间所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求的报文段。 


CLOSING:
这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也就会出现CLOSING状态,表示双方都正在关闭SOCKET连接。


CLOSE_WAIT(服务端状态):
这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是查看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。


LAST_ACK(服务端状态):
这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

 

状态迁移过程:

  a、客户端:

    CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

  b、服务端

    CLOSED->LISTENING->SYN_RECEIVED->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

在众多状态中,经常关注的有两个:TIME_WAIT、CLOSE_WAIT。

参考链接:https://www.cnblogs.com/jessezeng/p/5617105.html

 

### 关于TCP三次握手四次挥手的解析 #### 一、TCP三次握手的过程 TCP协议通过三次握手来建立可靠连接。以下是其具体过程: 1. **第一次握手**:客户端向服务器发送一个 SYN 数据包,表示希望与服务器建立连接,并随机生成初始序列号 X (SYN=1, seq=X),随后进入 SYN_SENT 状态[^1]。 2. **第二次握手**:服务器接收到客户端的数据包后,如果同意建立连接,则会返回一个 SYN ACK 数据包给客户端,其中 SYN 表示服务器也想与客户端建立连接并随机生成自己的初始序列号 Y (SYN=1, seq=Y),而 ACK 则是对客户端之前发出的 SYN 请求进行确认 (ACK=1, ack=X+1)[^2]。此时服务器处于 SYN_RCVD 状态。 3. **第三次握手**:当客户端收到来自服务器的响应后,它再回复一个 ACK 数据包给服务器作为最终确认 (SYN=0, ACK=1, seq=X+1, ack=Y+1)。一旦这个数据包到达服务器端,双方都进入了 ESTABLISHED 状态,意味着连接正式建立完成[^3]。 #### 二、TCP四次挥手的过程 为了终止一条已经存在的TCP连接,通常采用的是所谓的“四次挥手”。下面是详细的步骤描述: 1. **第一步**:主动关闭方(通常是客户端)先发起结束请求,发送带有FIN标志位设置为1以及当前序列号X的一个段到被动关闭方(一般是服务器),然后自己进入到 FIN_WAIT_1 状态[^4]。 2. **第二步**:被动关闭方接收到上述消息以后回应一个包含有对前面提到的那个FIN标记进行了应答(acknowledgment number 设置成了X+1) 并且保持自身原有的序列号不变(SYN=0, ACK=1, seq=W, ack=X+1) 的ACK段回到主动关闭方那里去;与此同时改变自身的状态成为CLOSED_WAIT 。这时前者则转变为FIN_WAIT_2 状态等待进一步的通知来自后者关于是否准备好完全切断这条线路的信息了。 3. **第三步**:只有等到所有的未决事务都被妥善解决之后——比如缓冲区内还有待传输或者接收的数据等等情况发生时才会继续下一步动作,在这个时候由原来的被动关闭者也就是现在的实际执行者再次送出另一个新的具有相同特征但是增加了额外参数fin_flag等于true再加上更新后的序列数值Z(W+length_of_data_sent_since_last_acknowledgement)+1这样一个完整的tcp segment对象传递回去告知对方现在可以安全地彻底分离彼此之间的联系关系啦!于是乎它的角色也随之转换成为了LAST_ACK模式下运作着的状态机器实例化版本形式存在于此期间之中直至最后阶段的到来为止。 4. **第四步**:最后一步就是当最初的提议者终于捕捉到了那个标志着整个流程即将圆满落幕的关键信号源—即最后一个携带fin标识符值设定了TRUE属性并且附带相应调整过的序列编号z+1的新鲜出炉的作品成果物送达之时起便立即切换至TIME-WAIT这种特殊类型的等候区间内停留固定时间长度两倍最大分组生存周期(Two Maximum Segment Lifetime ,简称2MSL )以便确保网络环境中可能残留下来的重复副本均已被有效清除干净后再从容不迫地步入终点线处实现真正的闭合操作从而顺利完成全部预定目标使命任务清单列表项目条目逐一勾选核销完毕无误之后方才安心退出舞台谢幕退场休息去了。 ```python def tcp_handshake(): """ Simulates the three-way handshake process of a TCP connection. Returns: str: A message indicating successful establishment of the connection. """ client_seq = random.randint(0, pow(2, 32)) server_seq = random.randint(0, pow(2, 32)) # Client sends SYN to Server syn_packet_client_to_server = {'SYN': True, 'SEQ': client_seq} # Server receives and responds with SYN-ACK syn_ack_packet_server_to_client = { 'SYN': True, 'ACK': True, 'SEQ': server_seq, 'ACK_NUM': client_seq + 1 } # Client acknowledges receipt from Server's response ack_packet_client_to_server = { 'ACK': True, 'SEQ': client_seq + 1, 'ACK_NUM': server_seq + 1 } return "Connection established successfully." def tcp_waveoff(): """ Simulates the four-way wave-off process when closing a TCP connection. Returns: str: A message indicating both sides have closed their connections properly after waiting periods are over. """ client_state = ['ACTIVE', 'FIN_WAIT_1', 'FIN_WAIT_2', 'TIME_WAIT'] server_state = ['LISTENING', 'CLOSE_WAIT', 'LAST_ACK'] # Assume initial states here... current_client_status_index = 0 current_server_status_index = 0 while not ((current_client_status_index >= len(client_state)-1) & \ (current_server_status_index >= len(server_state))): if current_client_status_index == 0: send_fin() current_client_status_index +=1 elif current_client_status_index==1 : receive_ack_for_previous_fin() current_client_status_index+=1 elif current_client_status_index==len(client_state)-1: wait_two_msl_period_before_closing_fully() else: pass # Other intermediate steps handled similarly... if current_server_status_index<len(server_state): handle_next_step_based_on_current_role_and_state(current_server_status_index) return "Both ends fully disconnected." ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值