计算机网络传输协议TCP三次握手与四次挥手原理(2)

只有等到Server端所有的报文都发送完了,所有的数据也处理完了之后,Server端才能发送FIN报文表示自己能够断开连接,因此不能一起发送。故需要四步握手。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

答:TCP连接是有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。

服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。

若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

为什么会有TIME_WAIT状态

现在做一个测试,首先启动server,然后启动client,然后用Ctrl-C使server终止,这时马上再运行server, 结果是:

计算机网络传输协议TCP三次握手与四次挥手原理

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

理解TIME_WAIT

TCP协议规定,主动关闭连接的一方要处于TIME_ WAIT状态,等待两个MSL(maximum segment lifetime)的时间后才能回到CLOSED状态.

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

MSL在RFC1122中规定为两分钟,但是各操作系统的实现不同, 在Centos7上默认配置的值是60s;

可以通过 cat /proc/sys/net/ipv4/tcp_fin_timeout 查看msl的值

我们来想一想,为什么TIME_WAIT的时间是2MSL

MSL是TCP报文的最大生存时间, 因此TIME_WAIT持续存在2MSL的话就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启, 可能会收到来自上一个进程的迟到的数据, 但是这种数据很可能是错误的);

同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失, 那么服务器会再重发一个FIN. 这时虽然客户端的进程不在了, 但是TCP连接还在, 仍然可以重发LAST_ACK);

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

在server的TCP连接没有完全断开之前不允许重新监听, 某些情况下可能是不合理的

服务器需要处理非常大量的客户端的连接(每个连接的生存时间可能很短, 但是每秒都有很大数量的客户端来请求).

这个时候如果由服务器端主动关闭连接(比如某些客户端不活跃, 就需要被服务器端主动清理掉), 就会产生大量TIME_WAIT连接.

由于我们的请求量很大, 就可能导致TIME_WAIT的连接数很多, 每个连接都会占用一个通信五元组(源ip,源端口, 目的ip, 目的端口, 协议). 其中服务器的ip和端口和协议是固定的. 如果新来的客户端连接的ip和端口号和TIME_WAIT占用的链接重复了,就会出现问题.

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

setsockopt

加上了setsockopt之后,ctrl+c终止服务器之后也可以马上启动服务器

setsocket

以上就是计算机网络传输协议TCP三次握手与四次挥手原理的详细内容,更多关于TCP三次握手与四次挥手的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwzygy.html