【计算机网络】Socket的SO_REUSEADDR选项与TIME_WAIT

news2025/2/3 4:08:40

SO_REUSEADDR用于设置套接字的地址重用。当一个套接字关闭后,它的端口可能会在一段时间内处于TIME_WAIT状态,此时无法立即再次绑定相同的地址和端口。使用SO_REUSEADDR选项可以允许新的套接字立即绑定到相同的地址和端口,即使之前的套接字仍处于TIME_WAIT状态。

TIME_WAIT状态的产生

客户端和服务器都可以主动发起关闭连接,上图是客户端主动发起的TCP连接关闭。首先调用close()发起主动关闭的一方,在发送最后一个ACK之后会进入time_wait的状态,也就说该发送方会保持2MSL时间之后才会回到初始状态。在time_wait的状态下,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。

MSL:Maximum Segment Lifetime,也就是最大报文生存时间 。

MSL到底是多长时间,可以通过下面的命令来查询,不同的操作系统时间不一样:

$ sysctl -a | grep "ipv4.tcp_fin_timeout"
sysctl: unable to open directory "/proc/sys/fs/binfmt_misc/"
net.ipv4.tcp_fin_timeout = 60

time_wait至少需要持续2MSL时长,这2个MSL中的第一个MSL是为了等自己发出去的最后一个ACK从网络中消失,而第二MSL是为了等在对端收到ACK之前的一刹那可能重传的FIN报文从网络中消失。如果time_wait时间是一个MSL,而time_wait结束后使用了相同的IP和Port建立了新的TCP连接,由于旧连接重传的FIN报文还没有在网络中消失,因此会干扰到新的TCP连接。

SO_REUSEADDR的使用

可以使用Socket类的setReuseAddress()方法来设置SO_REUSEADDR选项的值。示例代码如下:

ServerSocket serverSocket1 = new ServerSocket();
serverSocket1.setReuseAddress(false);
serverSocket1.bind(new InetSocketAddress(8099));
serverSocket1.close();

使用SO_REUSEADDR选项时有两点需要注意:

  1. 必须在调用bind方法之前使用setReuseAddress方法来打开SO_REUSEADDR选项。因此,要想使用SO_REUSEADDR选项,就不能通过Socket类的构造方法来绑定端口。

  2. 必须将绑定同一个端口的所有的Socket对象的SO_REUSEADDR选项都打开才能起作用。

SO_REUSEADDR异常的演示

Socket服务端代码如下:

package com.morris.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * Socket客户端,演示SO_REUSEADDR
 *
 * @see java.net.SocketOptions
 */
public class ReuseAddressServerDemo {
    public static void main(String[] args) throws IOException {

        ServerSocket serverSocket1 = new ServerSocket();
        System.out.println(serverSocket1.getReuseAddress());
        // serverSocket1.setReuseAddress(false);
        serverSocket1.bind(new InetSocketAddress(8099));
        Socket socket = serverSocket1.accept();
        socket.getOutputStream().write("hello".getBytes(StandardCharsets.UTF_8));
        socket.close();
    }
}

Socket客户端代码如下:

package com.morris.socket;

import java.io.IOException;
import java.net.Socket;

/**
 * Socket客户端,演示SO_REUSEADDR
 *
 * @see java.net.SocketOptions
 */
public class ReuseAddressClientDemo {
    public static void main(String[] args) throws IOException {
        // 这里只建立连接,不发送数据,也不接受数据,也不关闭连接,这样服务端才会出现TIME_WAIT
        new Socket("172.24.104.61", 8099);
        System.in.read();
    }
}

当客户端与服务端建立连接后,服务端发完数据就会立即关闭,此时会进入TIME_WAIT状态:

$ netstat -anotp| grep 8099
tcp6       0      0 172.24.104.61:8099      172.24.104.61:54542     FIN_WAIT2   -                    timewait (57.97/0/0)

我们可以看到四元组172.24.104.61:8099,172.24.104.61:54542代表的这个链接已经进入FIN_WAIT2状态,而且还需要等待57.97s才能进入CLOSE状态。

SO_REUSEADDR选项为true,也就是serverSocket1.setReuseAddress(true),也可以不进行设置,因为默认就是true,允许地址重用,此时再次启动ReuseAddressServerDemo程序,能够成功启动不会抛出端口被占用的异常。

SO_REUSEADDR选项为false,也就是serverSocket1.setReuseAddress(false),不允许地址重用,此时再次启动ReuseAddressServerDemo程序,就会抛出下面的异常:

Exception in thread "main" java.net.BindException: Address already in use
        at java.base/sun.nio.ch.Net.bind0(Native Method)
        at java.base/sun.nio.ch.Net.bind(Net.java:555)
        at java.base/sun.nio.ch.Net.bind(Net.java:544)
        at java.base/sun.nio.ch.NioSocketImpl.bind(NioSocketImpl.java:640)
        at java.base/java.net.ServerSocket.bind(ServerSocket.java:392)
        at java.base/java.net.ServerSocket.bind(ServerSocket.java:340)
        at com.morris.socket.ReuseAddressServerDemo.main(ReuseAddressServerDemo.java:20)

这时只有等四元组172.24.104.61:8099,172.24.104.61:54542代表的这个链接进入CLOSE状态后才能再次启动ReuseAddressServerDemo程序。

SO_REUSEADDR的注意事项与使用场景

在使用SO_REUSEADDR选项时,需要注意以下几点:

  • SO_REUSEADDR选项必须在调用bind()函数之前设置,否则设置不会生效。

  • 在使用SO_REUSEADDR选项时,需要确保不同的套接字使用相同的协议、地址和端口组合。

  • 使用SO_REUSEADDR选项不能使不同的线程或进程监听相同的端口,实现端口服用。

使用场景:

  • 服务器程序重启:当服务器程序需要重启时,为了避免等待操作系统回收端口的时间,可以设置SO_REUSEADDR选项。这样,重启后的服务器程序可以快速绑定到之前使用的端口上,实现快速恢复服务。

  • 测试和调试:在开发和测试阶段,可能需要频繁地启动和停止服务器。使用SO_REUSEADDR可以使得测试更加方便,因为不需要担心地址和端口已经被其他进程使用的问题。

time_wait产生的危害以及如何解决

大量的time_wait产生需要的条件:

  • 高并发

  • 服务器主动关闭连接

如果服务器不主动关闭连接,那么TIME_WAIT就是客户端的事情了

在高并发短连接的TCP服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量socket处于time_wait状态。在time_wait的状态下,定义这个连接的四元组(客户端IP地址和端口,服务端IP地址和端口号)不能被使用。因此,高并发可以让服务器在短时间范围内同时占用大量端口。如果客户端的并发量持续很高,此时部分客户端就会因为端口已经被占用而显示连接不上。

如何解决大量time_wait产生的危害?

  • 调整优化linux内核参数:出现大量TIME_WAIT的情况,一般是服务端没有及时回收端口,可以缩减time_wait时间。

  • 服务器不主动关闭连接

  • 重用端口:设置套接字选项为SO_REUSEADDR,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。

  • 使用长连接:HTTP请求的头部,connection设置为keep-alive

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1427620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何使用Linux Archcraft结合内网穿透实现SSH远程连接

📑前言 本文主要是使用Linux Archcraft结合内网穿透实现SSH远程连接的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页放风讲故事 &#…

过年了,程序员们,请多关照自己!休息是为了走得更远!

文章目录 过年了,程序员们,请多关照自己!一、理解“卷”背后的代价二、休息是为了走得更远三、关注健康,远离“过劳”四、平衡工作与生活,追求全面发展 过年了,程序员们,请多关照自己&#xff0…

input框前面名字长短不一时,让上下input框对齐方法

没设置之前 设置之后&#xff1a; 代码如下&#xff1a; <style>div{width: 500px;}label {display: block; /* 设置 label 元素为块级元素 */text-align: right; /* 设置文本右对齐 */margin-bottom: 10px; /* 设置标签之间的间距 */} </style> </head><…

Aigtek射频功率放大器有哪些具体应用

射频功率放大器是一种用于增加射频信号功率的电子器件。它在众多领域中有着广泛的具体应用&#xff0c;下面安泰电子将详细介绍几个主要的应用领域。 无线通信&#xff1a;射频功率放大器在无线通信系统中扮演着重要的角色。在移动通信领域&#xff0c;如蜂窝网络和卫星通信系统…

Solidworks 与 MATLAB 联合仿真

本文主要讲解了“MATLAB与SolidWorks的联合仿真怎么实现”&#xff0c;文中的讲解内容简单清晰&#xff0c;易于学习与理解&#xff0c;下面请大家跟着小编的思路慢慢深入&#xff0c;一起来研究和学习“MATLAB与SolidWorks的联合仿真怎么实现”吧&#xff01; 下载插件。 1、…

linux免密登录的实现

ssh免密登录使用方便&#xff0c;关键没有了口令验证反倒规避了暴力破解或者被探测的风险。配置得当&#xff0c;使用ssh免密登录更加安全。在生产环境中应用和数据库服务器之间互相设置后使用方便&#xff0c;并且在第三方人员配置使用时不用告知对方密码。 第一步、ssh登录发…

Python itertools模块:生成迭代器(实例分析)

itertools 模块中主要包含了一些用于生成迭代器的函数。在 Python 的交互式解释器中先导入 itertools 模块&#xff0c;然后输入 [e for e in dir(itertools) if not e.startswith(_)] 命令&#xff0c;即可看到该模块所包含的全部属性和函数&#xff1a; >>> [e for …

RabbitMQ控制台的基本使用

启动RabbitMQ后&#xff0c;浏览器 http://localhost:15672 打开RabbitMQ的控制台页面后&#xff0c;登录默认账户guest。 一. 添加队列 控制台选择队列&#xff0c;然后选择添加队列&#xff0c;队列类型默认经典类型&#xff0c;然后输入队列名称&#xff0c;最后添加队列。…

JSP和JSTL板块:第三节 JSP四大域对象 来自【汤米尼克的JAVAEE全套教程专栏】

JSP和JSTL板块&#xff1a;第三节 JSP四大域对象 一、page范围二、request范围三、session范围四、application范围 在服务器和客户端之间、各个网页之间、哪怕同一个网页之内&#xff0c;总是需要传递各种参数值&#xff0c;这时JSP的内置对象就是传递这些参数的载具。内置对象…

JeecgBoot jmreport/loadTableData RCE漏洞复现(CVE-2023-41544)

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

虫情监测设备能够自动识别病虫害

TH-CQ3S虫情监测设备的工作原理主要是通过高清摄像头拍摄农田的实时图像&#xff0c;利用图像识别技术对图像中的病虫害进行自动识别。一旦发现病虫害&#xff0c;设备会自动发出警报&#xff0c;并通过手机APP通知农民。农民可以根据设备提供的预测预报&#xff0c;及时采取防…

API攻击是什么?如何做好防范

API 攻击是针对应用程序接口的一种攻击手段&#xff0c;近年来逐渐成为网络安全领域的热点话题。攻击者主要针对应用程序接口中的漏洞或者错误进行API攻击&#xff0c;从而达到窃取敏感数据、进行恶意操作、破坏系统正常运行等恶意目的。 什么是API攻击&#xff1f; API 攻击是…

window 安装 jenkins 编写脚本

set JAVA_HOMED:\RuanJianKaiFa\jdk\jdk11 set CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOMe%\lib\tools.jar; set Path%JAVA_HOME%\bin; java -jar jenkins.war 下载jenkins.war包&#xff0c;编写一个txt文档&#xff0c;把脚本复制进去&#xff0c;修改文件后缀为.bat文件…

【MySQL】MySQL库

使用C/C语言链接MySQL 一、mysql connect二、mysql 接口介绍1. 初始化 mysql_init()2. 链接数据库 mysql_real_connect()3. 执行 mysql 命令 mysql_query()4. 获取执行结果 mysql_store_result()5. 释放空间5. 关闭 mysql 链接 mysql_close() 一、mysql connect 要使用C语言连…

【JavaEE进阶】 图书管理系统开发日记——贰

文章目录 &#x1f332;前言&#x1f384;设计数据库&#x1f343;引⼊MyBatis和MySQL驱动依赖&#x1f333;Model创建&#x1f38d;约定前后端交互接口&#x1f340;服务器代码&#x1f6a9;控制层&#x1f6a9;业务层&#x1f6a9;数据层 &#x1f334;效果展示⭕总结 &#…

亚马逊速卖通shein测评补单,轻松获得高评店铺订单暴涨人气火爆

测评之所以被认为是最快速有效的推广方式&#xff0c;是因为它能够迅速影响多个关键因素。通过测评&#xff0c;您能够快速提升关键词的转化率&#xff0c;从而获得更好的搜索排名。优质的评价有助于增加产品的权重和转化率&#xff0c;进一步提升排名。同时&#xff0c;增加的…

whistle抓包时如何过滤掉无用的链接

whistle在抓包的时候经常会有一些图片等我们不需要的地址&#xff0c;过多时会影响到我们抓的接口的速度&#xff0c;如何能快速的过滤掉无用的链接呢 可以在setting下进行如下设置 Exclude Filter&#xff1a;排除筛选器&#xff0c;即勾选后会排除勾选框下的地址链接Includ…

重写Sylar基于协程的服务器(3、协程模块的设计)

重写Sylar基于协程的服务器&#xff08;3、协程模块的设计&#xff09; 重写Sylar基于协程的服务器系列&#xff1a; 重写Sylar基于协程的服务器&#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar&#xff09; 重写Sylar基于协程的服务器&#xff08;1、日志模…

千卡训练有效时间占比超过95%,蚂蚁集团AI Infra技术开源

近日&#xff0c;蚂蚁集团AI创新研发部门NextEvo全面开源AI Infra技术&#xff0c;可帮助大模型千卡训练有效时间占比超过95%&#xff0c;能实现训练时“自动驾驶”&#xff0c;这推动了AI研发效率。 &#xff08;图&#xff1a;蚂蚁集团的自动化分布式深度学习系统DLRover现已…

7+双样本孟德尔随机化“得分神器”的双向孟德尔果然名不虚传

今天给同学们分享一篇生信文章“Bidirectional Mendelian randomization analysis of the genetic association between primary lung cancer and colorectal cancer”&#xff0c;这篇文章发表在J Transl Med期刊上&#xff0c;影响因子为7.4。 结果解读&#xff1a; MR分析结…