Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题( 九 )
也就是说 , TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收 , 从而帮助其正常关闭 。
假设 TIME-WAIT 没有等待时间或时间过短 , 断开连接会造成什么问题呢?
本文插图
没有确保正常断开的异常
- 如上图红色框框客户端四次挥手的最后一个 ACK 报文如果在网络中被丢失了 , 此时如果客户端 TIME-WAIT 过短或没有 , 则就直接进入了 CLOSE 状态了 , 那么服务端则会一直处在 LASE-ACK 状态 。
- 当客户端发起建立连接的 SYN 请求报文后 , 服务端会发送 RST 报文给客户端 , 连接建立的过程就会被终止 。
- 服务端正常收到四次挥手的最后一个 ACK 报文 , 则服务端正常关闭连接 。
- 服务端没有收到四次挥手的最后一个 ACK 报文时 , 则会重发 FIN 关闭连接报文并等待新的 ACK 报文 。
TIME_WAIT 过多有什么危害?
如果服务器有处于 TIME-WAIT 状态的 TCP , 则说明是由服务器方主动发起的断开请求 。
过多的 TIME-WAIT 状态主要的危害有两种:
- 第一是内存资源占用;
- 第二是对端口资源的占用 , 一个 TCP 连接至少消耗一个本地端口;
net.ipv4.ip_local_port_range
如果服务端 TIME_WAIT 状态过多 , 占满了所有端口资源 , 则会导致无法创建新连接 。
如何优化 TIME_WAIT?
这里给出优化 TIME-WAIT 的几个方式 , 都是有利有弊:
- 打开 net.ipv4.tcp_tw_reuse 和 net.ipv4.tcp_timestamps 选项;
- net.ipv4.tcp_max_tw_buckets
- 程序中使用 SO_LINGER, 应用强制使用 RST 关闭 。
如下的 Linux 内核参数开启后 , 则可以复用处于 TIME_WAIT 的 socket 为新的连接所用 。
net.ipv4.tcp_tw_reuse = 1
使用这个选项 , 还有一个前提 , 需要打开对 TCP 时间戳的支持 , 即
net.ipv4.tcp_timestamps=1(默认即为 1)
这个时间戳的字段是在 TCP 头部的「选项」里 , 用于记录 TCP 发送方的当前时间戳和从对端接收到的最新时间戳 。
由于引入了时间戳 , 我们在前面提到的 2MSL 问题就不复存在了 , 因为重复的数据包会因为时间戳过期被自然丢弃 。
温馨提醒:net.ipv4.tcp_tw_reuse要慎用 , 因为使用了它就必然要打开时间戳的支持 net.ipv4.tcp_timestamps , 当客户端与服务端主机时间不同步时 , 客户端的发送的消息会被直接拒绝掉 。 小林在工作中就遇到过 。。。 排查了非常的久
方式二:net.ipv4.tcp_max_tw_buckets
这个值默认为 18000 , 当系统中处于 TIME_WAIT 的连接一旦超过这个值时 , 系统就会将所有的 TIME_WAIT 连接状态重置 。
这个方法过于暴力 , 而且治标不治本 , 带来的问题远比解决的问题多 , 不推荐使用 。
方式三:程序中使用 SO_LINGER
我们可以通过设置 socket 选项 , 来设置调用 close 关闭连接行为 。
struct linger so_linger;so_linger.l_onoff = 1;so_linger.l_linger = 0;setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger,sizeof(so_linger));
推荐阅读
- 『Java』java数据结构系列——什么是数据结构
- 『Java』马云:成功人跟普通人差不多,但这三点我一定要分享给所有年轻人
- 小谢娱乐哦引来广大网友狂点赞,直呼炸天,程序员用Java实现扫雷小游戏
- 「客户端」学习网络编程,不了解TCP协议?难怪面试被刷下去,还不来学习!
- 体坛焦点全场吊打对手,上港苦主独造三球,4-0狂胜!申花亚冠劲敌踢疯了
- #Java#java线程到底有多少种状态?
- 【皇室战争】皇室战争:狂暴模式被吊打?学会这套卡组,轻松连胜拿奖励
- Muster电竞单挑省级马超惨遭吊打,网友:真香,国服瑶妹打脸梦泪失败
- 星空游戏精选小羊火龙溢出严重,法师吊打满配物理队?明日方舟高台输出太强
- #智能手表#1、初识java-1
