本文主要涉及到TCP的连接机制及其过程详解,TIME_WAIT状态详解,以及为什么需要三次握手和四次挥手,如果有错误,感谢大佬们指正。

一:TCP连接管理机制
TCP连接管理机制

服务器状态转化:
1.CLOSED -> LISTEN:服务器创建监听套接字后进入LISTEN状态,等待客户端建立连接;
2.LISTEN -> SYN_RCVD:当监听到连接请求(SYN),就将该连接放入内核等待队列,并给客户端发送ACK确认;
3.SYN_RCVD -> ESTABLISHED:当再次收到客户端的ACK确认报文,就建立一个新连接,进入WSTABLISHED状态,此时可以读写数据;
4.ESTABLISHED -> CLOSE_WAIT:当客户端主动断开连接,服务器收到FIN结束报文段,此时服务器发送ACK确认报文,并进入CLOSE_WAIT状态;
5.CLOSE_WAIT -> LAST_ACK:处理完之前的数据,服务器就调用close关闭连接,并发送FIN结束报文段,进入LAST_ACK状态等待客户端最后一个ACK确认;
6.LAST_ACK -> CLOSED:收到了客户端对结束报文段的ACK确认,彻底关闭连接。

客户端状态转化:
1.CLOSED ->SYN_SENT:开始connect,向服务器发送同步报文段;
2.SYN_SENT -> ESTABLISHED:收到了服务器的同步报文段和ACK确认,则客户端认为连接建立好,此时进入ESTABLISHED状态,可以读写数据;
如果三次握手时最后一次报文丢失,客户端会认为建立好了连接,然而服务器认为没有建立好连接,此时服务器给客户端一个RST响应,告诉客户端并没有建立连接。当客户端收到该响应:应重新建立连接或关闭老连接。(复位报文段)

3.ESTABLISHED -> FINWAIT 1:客户端主动调用close时,向服务器发送结束报文段,并进入FINWAIT 1状态;
4.FINWAIT 1 -> FINWAIT 2:当收到服务器对结束报文的ACK确认,客户端进入FINWAIT 2状态,等待服务器的FIN结束报文段;
5.FINWAIT 2 -> TIME_WAIT:当客户端收到服务器的结束报文段,会进入TIME_WAIT状态,并向服务器发送最后一次ACK确认了结束报文;
6.TIME_WAIT -> CLOSED:客户端会等待2MSL(两个报文生存最大时间),才进入CLOSED彻底关闭连接。

二:TIME_WAIT状态详解

首先做一个实验来验证TIME_WAIT是存在的:
这个实验是基于一个网络版本的计算器,我先启动服务器,再启动客户端:
TCP连接管理机制
之后我终止客户端,然后立刻再次运行客户端,发现出了问题:
TCP连接管理机制

而问题的原因正是虽然服务器被终止了,但TCP连接并没有完全断开,主动断开连接的一方进入TIME_WAIT状态,等待两个MSL(报文生存最大时间)后才能回到CLOSED状态,此时8080这个端口号仍然被占用。

TIME_WAIT的原因
举个例子:我是计算机学院的学生,计算机学院通知明天早上七点在教一101教室开会,到了第二天我由于种种原因,到了指定的教室已经是早上十点了,已经是别的学院在教室开会了。
所以,院长决定,等一段时间,等迟到的人都来了,再结束会议。

1.等待两个报文的最大生存时间,就能保证两个传输方向上未被接收或迟到的报文段消散;
2.保证最后一次ACK可靠到达(因为最后一次ACK可能丢失,主动断开连接的一方要等待:如果对端重发了FIN,则最后一次ACK丢失;若没收到,则发送成功。)

如何解决因为TIME_WAIT引起的bind失败
在某些场景下,服务器的TCP连接在没有完全断开之前不允许重新监听是不合理的:
服务器每秒都要处理十分大量的客户,但每个链接的生存时间都很短;此时如果某些客户端不活跃,被服务器主动断开连接(比如电脑登陆qq,长时间不动),就会产生大量的TIME_WAIT状态从而导致服务器的端口号不够用,无法建立新连接。

解决方法:

TCP连接管理机制

三:三次握手的原因

如果是两次握手,当服务器收到客户端发送的SYN同步报文段之后则认为连接建立,然后会维护该连接,将该连接组织管理起来,进入ESTABLISHED状态,并发送ACK报文段给客户端;
客户端收到ACK后才会进入ESTABLISHED状态建立连接。如果ACK丢包,客户端会认为连接没有建立,而重新向服务器发送重复的SYN报文段,服务器接收后会再次建立该连接,而维护连接是消耗资源的,如果ACK一直丢失,客户端会一直发送SYN,服务器就会建立很多相同的无效的连接,从而使服务器资源浪费,使服务器受到影响。

如果是三次握手,当客户端收到来自服务器的SYN+ACK后,会进入ESTABLISHED状态,并建立和维护该连接;
客户端会发送ACK确认报文,服务器收到了才会进入ESTABLISHED状态并建立维护连接;
即使最后一次ACK‘丢失,客户端认为建立好了连接,然而服务器认为没有建立好连接,此时服务器给客户端一个RST响应,告诉客户端并没有建立连接。当客户端收到该响应:应重新建立连接或关闭老连接。虽然客户端会建立一些无效连接,会受到影响,但是服务器并没有受到影响,从而保证了服务器的安全。同时客户端虽然受到了影响,但随后会重新建立连接,所以会减小影响。

总结一下:
1.两次握手可能会使服务器建立很多无效连接,浪费资源;
2.虽然三次握手可能会使客户端受影响,但随后会重建;
3.三次就够了,不需要更多次握手。

四:四次挥手的原因
四次挥手比较容易理解,就和情侣分手一样,分手是双方的事,必须要双方都同意,双方都确认,比较难理解的是TIME_WAIT。

相关文章:

  • 2022-03-02
  • 2022-01-16
  • 2021-07-22
  • 2021-04-30
  • 2021-04-05
  • 2021-12-14
  • 2022-12-23
  • 2021-10-11
猜你喜欢
  • 2021-07-01
  • 2022-01-07
  • 2021-10-04
  • 2021-05-24
相关资源
相似解决方案