REUSEPORT-REUSEADDR-学习

tcp 端口复用与惊群效应(REUSEADDR、REUSEPORT) 我在之前的一篇文章中,介绍了我在之前的项目中遇到的端口复用,windows 的udp里端口复用导致了一个bug,具体的链接参考如下: 关于Socket中端口复用_zhc的博客-优快云博客_socket端口复用 而我现在是想总结一下,linux下的情况,想从头再梳理下,REUSEADDR 和 REUSEPORT的作用。 1.SO_REUSEADDR 是为了解决time_wait问题而产生的 SO_REUSEADDR 它的作用是当服务器端主动断开链接的时候,处在timewait阶段大约60秒钟,服 阅读详情

简介

记录一下stackoverflow关于 SO_REUSEPORT SO_REUSEADDR 两个选项的解释。

理论

SO_REUSEADDR

如果在绑定套接字之前在套接字上启用了SO_REUSEADDR,则可以成功绑定该套接字,除非与绑定到完全相同的源地址和端口组合的另一个套接字发生冲突。现在你可能想知道这和以前有什么不同?关键词是“完全正确”。因此,REUSEADDR主要改变了在搜索冲突时处理通配符地址(“任何IP地址”)的方式。

测试结果:

SO_REUSEADDRsocketAsocketBResult
ON/OFF192.168.0.1:21192.168.0.1:21Error (EADDRINUSE)
ON/OFF192.168.0.1:2110.0.0.1:21OK
ON/OFF10.0.0.1:21192.168.0.1:21OK
ON/OFF0.0.0.0:210.0.0.0:21Error (EADDRINUSE)
OFF0.0.0.0:21192.168.1.0:21Error (EADDRINUSE)
OFF192.168.1.0:210.0.0.0:21Error (EADDRINUSE)
ON0.0.0.0:21192.168.1.0:21OK
ON192.168.1.0:210.0.0.0:21OK

套接字有一个发送缓冲区,如果对send()函数的调用成功,并不意味着请求的数据实际上已经发送出去,它只意味着数据已经添加到发送缓冲区。对于UDP套接字,数据通常会很快发送,如果不是立即发送,但是对于TCP套接字,在向发送缓冲区添加数据和让TCP实现真正发送数据之间可能会有相对较长的延迟。因此,当您关闭TCP套接字时,发送缓冲区中可能仍有挂起的数据,该数据尚未发送,但您的代码认为它已发送,因为send()调用已成功。如果TCP实现在您请求时立即关闭套接字,那么所有这些数据都将丢失,您的代码甚至不知道这一点。TCP被认为是一种可靠的协议,像这样丢失数据不是很可靠。这就是为什么当你关闭一个仍然有数据要发送的套接字时,它会进入一种称为TIME_WAIT的状态。在该状态下,它将等待所有挂起的数据成功发送,或者等待超时,在这种情况下,套接字将强制关闭。

内核在关闭套接字之前等待的时间量,不管它是否仍有数据在传输中,都称为延迟时间。在大多数系统上,延迟时间是全局可配置的,默认情况下相当长(在许多系统上,两分钟是一个常见值)。它还可以使用socket选项为每个socket配置,因此可以使用socket选项使超时更短或更长,甚至完全禁用超时。但是,完全禁用它是一个非常糟糕的主意,因为优雅地关闭TCP套接字是一个稍微复杂的过程,需要来回发送两个数据包(以及在数据包丢失时重新发送这些数据包),而整个关闭过程也受到延迟时间的限制。如果禁用“延迟”,套接字可能不仅会在传输过程中丢失数据,而且总是强制关闭而不是优雅地关闭,这通常是不推荐的。有关如何优雅地关闭TCP连接的详细信息超出了本回答的范围,如果您想了解更多信息,建议您查看本页。即使您禁用了延迟SO_LINGER,如果您的进程在没有明确关闭套接字的情况下死亡,BSD(可能还有其他系统)仍然会延迟,忽略您配置的内容。例如,如果您的代码只调用exit()(对于小型、简单的服务器程序来说非常常见),或者进程被信号终止(这包括它可能只是因为非法内存访问而崩溃)。因此,您无法确保套接字在任何情况下都不会出现。

问题是,系统如何处理状态为TIME_WAIT的套接字?如果未设置SO_REUSEADDR,则状态为TIME_WAIT的套接字仍被视为绑定到源地址和端口,任何将新套接字绑定到相同地址和端口的尝试都将失败,直到套接字真正关闭为止,这可能需要与配置的延迟时间一样长的时间。因此,不要期望在关闭套接字后可以立即重新绑定它的源地址。在大多数情况下,这将失败。但是,如果为您尝试绑定的套接字设置了SO_REUSEADDR,那么在TIME_WAIT状态下绑定到相同地址和端口的另一个套接字将被忽略,毕竟它已经“半死不活”,并且您的套接字可以绑定到完全相同的地址而不会出现任何问题。在这种情况下,另一个套接字可能具有完全相同的地址和端口并不起作用。请注意,如果另一个套接字仍在“工作”,则将套接字绑定到时间等待状态下与死亡套接字完全相同的地址和端口可能会产生意外的、通常是不希望的副作用,但这超出了本答案的范围,幸运的是,这些副作用在实践中相当罕见。

还有最后一件事你应该知道。只要要绑定到的套接字启用了地址重用,上面写的所有内容都可以工作。另一个套接字(已绑定或处于TIME_WAIT状态的套接字)在绑定时也不必设置此标志。决定绑定是成功还是失败的代码只检查馈入bind()调用的套接字的SO_REUSEADDR标志,对于所有其他已检查的套接字,甚至不查看该标志。

可以构造一个这样的测试,将SO_LINGER设置很长时间。开启SO_REUSEADDR,socketA发送数据并且关闭,socketB重新bind这个地址,应该是能成功的。

SO_REUSEPORT

所以,大多数人都会期望它会是这样。基本上,SO_REUSEPORT允许您将任意数量的套接字绑定到完全相同的源地址和端口,只要之前绑定的所有套接字在绑定之前也设置了SO_REUSEPORT。如果绑定到地址和端口的第一个套接字未设置SO_REUSEPORT,则在第一个套接字再次释放其绑定之前,任何其他套接字都不能绑定到完全相同的地址和端口,无论该其他套接字是否设置了SO_REUSEPORT。与SO_REUSEADDR的情况不同,处理SO_REUSEPORT的代码不仅会验证当前绑定的套接字是否设置了SO_REUSEPORT,而且还会验证具有冲突地址和端口的套接字在绑定时是否设置了SO_REUSEPORT。

SO_REUSEPORT并不意味着SO_REUSEADDR。这意味着,如果一个套接字在绑定时没有设置SO_REUSEPORT,而另一个套接字在绑定到完全相同的地址和端口时设置了SO_REUSEPORT,则绑定会失败,这是预期的,但如果另一个套接字已经死亡并且处于TIME_WAIT状态,则绑定也会失败。为了能够在时间等待状态下将套接字绑定到与另一个套接字相同的地址和端口,需要在该套接字上设置SO_REUSEADDR,或者在绑定之前必须在两个套接字上都设置SO_REUSEPORT。当然,允许在套接字上同时设置SO_REUSEPORT和SO_REUSEADDR。

关于SO_REUSEPORT,除了它是在SO_REUSEADDR之后添加的之外,没有更多的内容可以说,这就是为什么在其他系统的许多套接字实现中找不到它,在添加此选项之前,它“分叉”了BSD代码,在此选项之前,无法将两个套接字绑定到BSD中完全相同的套接字地址。

实践

如何查看系统的版本

[root@test-qingzhou-01 ~]# hostnamectl
Static hostname: test-qingzhou-01
Icon name: computer-vm
Chassis: vm
Machine ID: 20190711105006363114529432776998
Boot ID: 2abf6a175d9e4dc4a16c0b28d262818b
Virtualization: kvm
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-957.21.3.el7.x86_64
Architecture: x86-64

相关代码

golang的代码

syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, boolint(ipv6only))
setsockopt

参考

UDP用户数据报协议 传输层 传输层负责将数据从发送端传输到接收端 TCP与UDP都属于传输层协议 端口号 通过IP与端口号可以在网络中确定一个唯一的进程 端口号可以标识一台主机上的唯一的一个进程 一个进程可以绑定多个端口号 可以通过源IP地址 目的IP地址 源端口号 目的端口号 协议的版本来确定一个唯一的通信 可以通过setsockopt()实现端口的复用 第三个参数使用SO_REUSEADD... 阅读详情

相关推荐

reuseaddr和reuseport

方案1: 如果socketA调用bind后,又调用了listen,则fastreuse 会恢复为0(即使socketA在bind前设置了SO_REUSEADDR),此时即使socketB在bind前设置了SO_REUSEADDR也不管用。三个匹配条件:sk_family ,socket绑定的本地ip rcv_saddr,socket绑定的本地接口sk_bound_dev_if。同一条tcp流的前两个建立连接的请求syn和响应ack报文需要走上面流程,连接建立后,后续报文到来后,可直接在已建立连接表查找到。.

fengcai_ke的博客 1260

网络编程中的SO_REUSEADDR和SO_REUSEPORT参数详解

在BSD中,SO_REUSEADDR选项有两个用户:setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,(const void *)&reuse , sizeof(int));目的:当服务端出现timewait状态的链接时,确保server能够重启成功。注意:SO_REUSEADDR只有针对time-wait链接(linux系统time-wait连接持续时间为1min),确保server重启成功的这一个作用。举个time_wait的连接通过so_reuseaddr选项

赶路人儿 6308

SO_REUSEADDR和SO_REUSEPORT异同,以及在不同操作系统的差异

SO_REUSEADDR和SO_REUSEPORT异同,以及在不同操作系统的差异

dvlinker的技术专栏 3572

TODO:Golang语言TCP/UDP协议重用地址端口

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34074740的博客 421

go-reuseport:在golang中重用tcpudp端口

去再利用 注意:此程序包需要> = 1.11。 此程序包允许从相同的TCP或UDP端口进行侦听和拨号。 这意味着可以设置以下sockopts: SO_REUSEADDR SO_REUSEPORT godoc: ://godoc.org/github.com/libp2p/go-reuseport 这是一个简单的程序包,可帮助地址重用。 这在尝试进行TCP NAT穿Kong时非常重要,这需要一个过程在同一TCP端口上进行侦听和拨号。 该软件包提供了一些实用程序,可在各种操作系统上启用此行为。 例子 // listen on the same port. oh yeah. l1 , _ := reuse . Listen ( "tcp" , "127.0.0.1:1234" ) l2 , _ := reuse . Listen ( "tcp" , "127.0.0.1:1234"

基于Python批量获取过去某地某时的天气数据

此段代码为经Visual Weather API官网样例后修改。原代码返回数据格式为json,经测试json风速字段不可用,后改为返回数据格式为csv。若修改weather_api_endpoint,还可获取该地点的预测数据,但返回数据字段可能发生变化,请以官网文档为准。获取到的字段包括:平均温度、露点、湿度、风速、降雨量、能见度、云量、天气类型等。目的:已知某一地址,获取过去某一时间该地的天气数据,并能够批量运行。这一步也会有获取不到的时间和地点,因此为空白。此段代码为经百度地图api官网样例后修改。

wiseman1233的博客 905

muduo网络库剖析——套接字Socket类

基于c++的muduo网络库开源项目深度剖析!超级加分的简历项目,期待您的讨论~

weixin_62021811的博客 1171

杭电计算机组成原理课程设计-实验七-寄存器堆设计实验

寄存器堆实验实验原理实验内容模块功能说明模块逻辑引脚图寄存器堆模块代码REG模块测试用例REG-ALU测试用例实验结果记录 寄存器堆实验结果及分析ALU_REG运算器模块实验结果及分析探索与思考 实验原理   32×32位的寄存器堆模块示意图如图所示,含有32个寄存器,每个寄存器32位。该寄存器堆具有A和B两个读端口,分别由 5 位的寄存器编号 R_Addr_A 和 R_Addr_B 来寻址 2 个寄存器,读出的数据则由 R_Data_A(32 位)和R_Data_B(32 位)输出。读访问时,没有使能或者

HDU-整蛊小子-⏰☂️/蚂蚁集团研发工程师 1万+

TCP/IP编程之SO_REUSEADDR和SO_REUSEPORT套接字选项

基本概念: SO_REUSEADDR套接字选项能起到以下4个不同的功用: (1)SO_REUSEADDR允许启动一个监听服务器并捆绑众所周知端口,即使以前建立的该端口用作它们的本地端口的连接仍存在。 这个条件通常是这样碰到的: a)启动一个监听服务器; b)连接请求到的,派生一个子进程来处理这个客户; c)监听服务器终止,但子进程继续为现有的连接上的客户提供服务; d)重启监听服

daiyudong2020的博客 1万+

Ansys Zemax与Speos协同设计:从HUD光学优化到驾驶环境可视化全流程解析

本文深入解析了如何利用Ansys Zemax与Speos进行协同设计,实现从HUD光学系统核心优化到驾驶环境可视化验证的全流程。文章强调了HUD设计是光学性能与视觉感知的深度耦合,通过Zemax进行精密光学设计,再利用Speos进行系统级仿真与感知模拟,最终完成从虚拟到现实的闭环验证,有效提升HUD产品的开发效率与可靠性。

weixin_29199873的博客 249

第六天 界面操作及美化(6.4 使用GUI 套件)

本文介绍如何使用VIPM工具安装DMC GUI套件:首先打开VIPM并连接网络,搜索"UI"找到DMCGUI套件后下载安装;安装完成后即可在VIPM中添加控件并预览效果。该方法同样适用于下载其他UI套件,用户可根据需求设计个性化界面。整个流程包括搜索、下载、安装和使用四个简单步骤,适合快速搭建GUI界面。

weixin_38637405的博客 407

REUSEPORT和REUSEADDR

TIME-WAIT状态以及其带来的问题 Created with Raphaël 2.1.2主机A主机A主机B主机BESTABLISHEDESTABLISHEDFIN = 1 , seq = iFIN-WAIT-1ACK = 1 , seq = j , ack = i+1CLOSE-WAITFIN-WAIT-2FIN = 1 , seq = k , ack = i+1LAST-ACKACK

runtian 1922

【常见开源库的二次开发】基于openssl的加密与解密——openssl认识与配置(一)

OpenSSL 是一个开源的软件库,它提供了一系列加密工具和协议,主要用于实现安全通信,如在网络上的数据传输。它支持多种加密算法,包括对称加密、非对称加密、散列函数、伪随机数生成器、数字签名、密钥交换以及证书管理等。

嵌入式技术开发 4161

浅析套接字中SO_REUSEPORT和SO_REUSEADDR的区别

讨论了SO_REUSEPORT和SO_REUSEADDR在BSD中的起源及其作用的区别。分析了不同操作系统中二者意义上的差别。

正西风落叶下长安 1万+

基于 高斯过程回归(Gaussian Process Regression, GPR) 的 时间序列区间预测 的 MATLAB 示例代码

基于 高斯过程回归(Gaussian Process Regression, GPR) 的 时间序列区间预测 的 MATLAB 示例代码

算法如诗的博客 154

delphi fmx android 自动更新(一)

所以,如果是http 则,manifest.xml application 下,https无需添加。增加android:usesCleartextTraffic="true",不然无法使用http下载东西。1,REQUEST_INSTALL_PACKAGES 权限。4,WRITE_EXTERNAL_STORAGE 权限。3,READ_EXTERNAL_STORAGE 权限。一般是从http下载安装包 apk。2,INTERNET 权限。sFile为apk包路径。

全粘工程师 550

SO_REUSEADDR与SO_REUSEPORT平台差异性总结

SO_REUSEADDR与SO_REUSEPORT平台差异性前言BSD系统Linux系统Windows参考文档 前言 在网上看到很多人说在socket中设置SO_REUSEADDR选项的用途是端口复用/地址复用,具体来说就是让处于time_wait状态的socket可以快速复用。对于服务端而言,设置SO_REUSEADDR作用就是在重启服务器时能马上重新绑上原来的端口,方便调试。不然就绑定会失败,...

u012324798的博客 1726

Unity3D实现视频和模型融合效果

在Unity中,视频和3D模型融合通常涉及到将视频表面内嵌到3D场景中。视频不影响模型的展示, 这可以通过使用Shader和Texture来实现。大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。下面就让我们进入正文吧!提示:以下是本篇文章正文内容,下面案例可供参考本次介绍的就是视频和模型融合的实现,以后有其他的需要添加的会继续添加不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒。

心疼你的一切博客 5357

SO_REUSEADDR和SO_REUSEPORT选项

    最近看redis源码,看到redis的网络模型,借机对socket编程和TCP/IP协议做了进一步的巩固和熟悉。其中对socket选项SO_REUSEADDR和SO_REUSEPORT写了一些demo,文章根据测试结果对SO_REUSEADDR选项和SO_REUSEPORT选项做一个总结,同时对博客的总结做一个纠正。     先来了解一下socket默认的行为:     ·每个TCP连...

孤独剑 4932

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

SO_REUSEADDR 和 SO_REUSEPORT 的区别 / Linux TCP SO_REUSEPORT — 使用和实现 ……

…

u013669912的博客 1631

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

SO_REUSEADDR & SO_REUSEPORT

SO_REUSEADDR 当有一个有相同本地地址和端口的socket1处于TIME_WAIT状态时,而你启动的程序的socket2要占用该地址和端口,你的程序就要用到该选项。 SO_REUSEADDR允许同一port上启动同一服务器的多个实例(多个进程)。但每个实例绑定的IP地址是不能相同的。在有多块网卡或用IP Alias技术的机器可 以测试这种情况。 SO_REUSEADDR允许单个进程绑定...

楚兴 1400

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

SO_REUSEADDR和SO_REUSEPORT

帮助理解C++网络编程的端口复用

weixin_46698687的博客 837

SO_REUSEADDR 和 SO_REUSEPORT 的区别和用法实例详细探究讲解

SO_REUSEADDR主要用来解决TIME_WAIT,SO_REUSEPORT解决端口可以重复调用问题,两者没有交集和冲突可以根据实际情况进行自由选择。

Wanglei110311089的博客 1365

Socket中SO_REUSEADDR/SO_REUSEPORT详解

目录 SO_REUSEADDR/SO_REUSEPORT到底什么意思? 设置SO_REUSEADDR选项 TIME_WAIT有什么意义呢? SO_REUSEADDR/SO_REUSEPORT到底什么意思? SO_REUSEADDR选项有如下语义: 这个套接字选项通知内核,如果端口忙,但TCP状态位于TIME_WAIT(Linux下的TIME_WAIT大概是2分钟) ,可以重用端口。如果端口忙,而TCP状态位于其他状态,重用端口时依旧得到一个错误信息,指明"地址已经使用中"。如果你的服务...

weixin_43606861的博客 864

socket:REUSEADDR与REUSEPORT选项

SO_REUSEADDR是创建socket时比较常用的选项,通过该选项让多个socket可以 bind相同的端口。

skysky97的博客 1489

终极解密:go-reuseport如何利用SO_REUSEADDR与SO_REUSEPORT实现端口复用

在网络编程中,端口复用是一项关键技术,尤其对于需要同时监听和拨号同一端口的场景(如TCP NAT打洞)至关重要。**go-reuseport** 是一个专为Go语言设计的库,通过封装底层系统调用,轻松实现TCP/UDP端口的复用功能。本文将深入解析其工作原理,帮助开发者快速掌握这一强大工具。 ## 什么是SO_REUSEADDR与SO_REUSEPORT? 在探讨 **go-reuseport

gitblog_00263的博客 829
上一篇: MySQL学习笔记
下一篇: gperftools使用
erlang_hell
博客等级 码龄14年 57粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值