网络基础——连接管理机制

在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。在之前的博客中,我们已经介绍过了TCP三次握手以及四次挥手的过程,现在我们就这个问题,从传输层的角度来探讨一下。

            

  • 三次握手

(1)客户端向服务器发送SYN信号,请求建立连接;

(2)服务器端接收到客户端的请求后,发送SYN+ACK信号,表示确认建立连接;

(3)客户端收到服务器端的反馈后,向服务器端发送ACK字段表示确认,同时状态变为ESTABLISHED,表示连接建立。

  • 四次挥手

(1)客户端向服务器发送FIN信号,表示通知对方,本端要关闭了;

(2)服务器端收到客户端的信号后,发送ACK信号表示确认;

(3)服务器端向客户端发送FIN信号,表示通知对方,本端也要关闭了;

(4)客户端收到后,也反馈给服务器端一个ACK信号,表示确认。

需要注意的是,在理解TCP三次握手以及四次挥手时,我们不仅要理解它们所发的字段的含义及意义,还要注意服务器端和客户端的状态改变

在之前博客的讨论中,我们已经解释过了为什么是三次握手和四次挥手。

三次挥手的优点:

    (1)保证服务器安全性;

    (2)成功率极高;

    (3)三次握手不一定会百分百的成功,它也有可能会失败,但是失败对于服务器端来说毫无影响,对客户端有影响,客户端可以通过发送RST重新建立连接。

注:TCP建立与释放连接是基于状态机的。


下图为TCP状态转换的一个汇总:

            

图中较粗的虚线代表服务端的状态变化情况;较粗的实线代表客户端的状态变化情况。

CLOSED是一个假想的起始点,不是真实状态。

  • 理解TIME_WAIT

我们先来做一个测试:先启动server,然后启动client,用Ctrl+C终止server进程,再马上运行server,结果如下所示。


这是因为,虽然server的应用程序终止了,但TCP协议层的连接并没有完全断开,因此不能再次监听同样的server端口。我们可以用netstat命令查看一下:


TCP协议规定,主动关闭连接的一方要处于TIME_WAIT状态,等待两个MSL(报文最大生存时间)的时间后才能回到CLOSED状态。

我们使用Ctrl+C终止了server进程,所以server是主动关闭连接的一方,在TIME_WAIT期间仍然不能再次监听同样的server端口。

MSL在Centos7上默认配置的值是60s。

我们可以通过cat  /proc/sys/net/ipv4/tcp_fin_timeout查看MSL的值:


从TIME_WAIT->CLOSED,客户端要等待一个2MSL的时间,才会进入CLOSED状态。

那么为什么TIME_WAIT的时间是2MSL呢?若客户端最后一次发送ACK给服务器端,所用时间最多为MSL。我们分两种情况来讨论:

    (1)当服务器端收到ACK,则断开连接,此后的MSL时间里客户端不会再收到信号;

    (2)当最后一次ACK丢失,服务器端没有收到,此时服务器端会重新发送FIN,这期间所用的总时间小于2MSL。

  • 解决TIME_WAIT状态引起的bind失败的方法

使用setsockopt()设置socket描述符的选项SO_REUSEADDR为1,表示允许创建端口号相同但IP地址不同的多个socket描述符。






猜你喜欢

转载自blog.csdn.net/cecilia3333/article/details/80355664
今日推荐