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

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_WAITnew 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 useat 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.hqwc.cn/news/444162.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

地理空间分析10——空间数据分析中的地理编码与Python

目录 写在开头1. 地理编码基础1.1 地理编码的基本原理1.1.1 坐标系统1.1.2 地名解析1.1.3 编码算法1.2 Python中使用地理编码的基础知识1.2.1 百度地图API1.2.2 高德地图API1.2.3 腾讯地图API1.3 Python中实现代码2. 逆地理编码2.1 利用Python进行逆地理编码2.1.1 获取高德地图…

使用Java实现HTTP持久连接:一次与网络的“长聊“

大家都知道,传统的HTTP连接就像是一次性的餐具,每发送一个请求,就得重新建立一个连接,然后快速用完就扔。这对于网络资源来说,简直就是一场"大肆挥霍"的派对。但幸好,我们有HTTP持久连接&#xf…

8、应急响应-战前溯源反制主机蜜罐系统HFishHIDSElkeidWazuh

用途:个人学习笔记,欢迎指正 目录 背景: 一、潮源反制-平台部署-蜜罐-Hfish 二、溯源反制-平台部署-HIDS-Wazuh 三、溯源反制-平台部署-HlDS-Elkeid-hub 背景: 攻击者对服务器存在着各种威胁行为,作为安全人员&am…

解决:ModuleNotFoundError: No module named ‘torchvision’

解决:ModuleNotFoundError: No module named ‘torchvision’ 文章目录 解决:ModuleNotFoundError: No module named torchvision背景报错问题报错翻译报错位置代码报错原因解决方法方法一,直接安装方法二,手动下载安装方法三&…

Mongodb安装Linux

确定你的CentOS 版本 使用以下命令: /etc/centos-release下载Mongodb 解压tgz压缩包 创建data和log文件夹 , 确定你的文件夹访问权限 在log文件夹里面创建mongodb.log文件(这一步很重要 ! ! !) touch mongodb.log创建mongodb.conf文件 在你的mongodb文件夹下 vi mongo…

color - 让你的输出带点颜色

color color 是一个可以让你输出带颜色文本的库。 安装 go get github.com/fatih/color示例 输出到控制台 // 这会直接输出到控制台 color.Cyan("Prints text in cyan.")// 每个调用末尾会自动加上换行 color.Blue("Prints %s in blue.", "text&…

使用orangepi玩linux

最近看了这个大佬的文章,写了使用远程来挂载linux的方案,觉得还是很有意思的,瞬间感觉linux这块都还是相通的,就跑了一下,果然,牛逼! 香橙派全志H3烧录Uboot,远程加载zImage&#xf…

羊奶指南又跟新了,又有新发现

羊奶指南又跟新了,又有新发现 羊奶源远流长,早在古代我们祖先就意识到了它的药用价值。在《本草纲目》一书中,药圣李时珍明确指出了羊奶的珍贵之处,为后人留下了宝贵的知识。本文将以科学的角度详细解读羊奶的药用价值&#xff0…

分享个前端工具-取色调色工具

这里虽然贴了两个,但推荐 Pipette. PipetteWin22.10.22.zip: https://download.csdn.net/download/rainyspring4540/88799632 图标: 界面: ColorPix https://download.csdn.net/download/rainyspring4540/88799642 图标: 界面…

HBase介绍

一、HBase简介 1.1、HBase是什么 Google在200-2006发表了GFS、MapReduce、BigTable三篇 论文 ,号称“三驾马车”,开启了大数据的时代。 GFS是Google File System,开源实现是HDFS(Hadoop File System)。 MapReduce…

LeetCode 828. 统计子串中的唯一字符

一开始想的是两次前缀和,发现自己蠢了 看了灵神的题解,类似于DP的思想 我们维护以每个字符串结尾的子字符串对答案的贡献,s[i]的贡献是多少?首先我们知道他需要自己单独一个串或者接在以s[i-1]结尾的那些字符串的后面&#xff0c…

乐鑫与 Elektor 杂志合作推出特刊,聚焦 AIoT 创新

在新一年的起始之际,我们很荣幸地与 Elektor 合作推出由乐鑫领衔编辑的杂志特刊。欢迎点此阅读电子版本。 Elektor 杂志作为国际电子工程和科技创新的重要平台,自 20 世纪 60 年代起,就引领着电子制造的发展潮流。如今,它已经发展…