SO_REUSEADDR与SO_REUSEPORT平台差异性总结

前言

在网上看到很多人说在socket中设置SO_REUSEADDR选项的用途是端口复用/地址复用,具体来说就是让处于time_wait状态的socket可以快速重新绑定原来的ip+port。对于服务端而言,设置SO_REUSEADDR作用就是在重启服务器时能马上重新绑上原来的端口,方便调试。不然就绑定会失败,提示ADDR已经在使用中——那只好等等再重试了,麻烦。
但我在Windows系统下的试验结果与这种说法不一致,再继续深入搜索下去,发现了关于SO_REUSEADDR与SO_REUSEPORT平台差异性的说法,又在Windows中试验了一下(其他平台没测试),基本一致,现总结如下。
注:以下结论只针对TCP连接。

BSD系统

SO_REUSEADDR选项作用

  1. 让处于time_wait状态的socket可以快速复用原ip+port(网上广泛流传的说法)
  2. 使得0.0.0.0(ipv4通配符地址)与其他地址(127.0.0.1和10.0.0.x)不冲突(详见此文章

SO_REUSEPORT选项作用

能够让多个socket同时绑定完全相同的ip+port,但不能实现负载均衡,似乎请求都是由后面绑定的socket接收(根据[SO_REUSEADDR与SO_REUSEPORT平台差异性]的实验结果(https://www.cnblogs.com/xybaby/p/7341579.html))。

Linux系统

SO_REUSEADDR选项作用

能让处于time_wait状态的socket可以快速复用原ip+port,不能解决监听端(服务端)通配符IP地址的冲突问题,但非监听端(客户端)可以解决。

SO_REUSEPORT选项作用

能够让多个socket同时绑定完全相同的ip+port,且能实现负载均衡。
内核将尝试在这些socket之间平均分配收到的连接请求,即Linux尝试了进行流量分配上的优化。比如一个简单的服务器进程的几个不同实例可以方便地使用SO_REUSEPORT来实现一个简单的负载均衡,而且这个负载均衡有内核负责, 对程序来说完全免费!

以下为本人试验结果,测试代码在这里。

Windows

  1. windows 下处于time_wait状态的socket默认就可以快速复用原ip+port,无需进行任何设置。即服务器重启时可以立即绑定原ip+port,不用设置socket选项(原因)。
  2. 没有SO_REUSEPORT选项,会报错。
  3. 只有SO_REUSEADDR选项,但其效果与BSD系统下的SO_REUSEPORT类似,即作用是同时绑定完全相同的ip+port,但不能实现负载均衡。

都设置SO_REUSEADDR
完全相同的ip+port可以同时绑定成功,但只有最先绑定的socket能接收请求,后面绑定的能监听,但接收不到请求。
不都设置SO_REUSEADDR
完全相同的ip+port无法绑定成功

不设置SO_REUSEADDR
(本机具体IP地址)172.20.10.5:8003
(localhost)127.0.0.1:8003
(通配符IP地址)0.0.0.0:8003
三者可以同时绑定成功
启动三个服务:前两个地址只能接收客户端请求的等于自己地址的连接,0.0.0.0接收不到发给前两个地址的连接。
启动两个服务,0.0.0.0和172.20.10.5:0.0.0.0可以接收127.0.0.1的连接,172.20.10.5自己接收自己的。
启动两个服务,0.0.0.0和127.0.0.1:0.0.0.0可以接收172.20.10.5的连接,127.0.0.1自己接收自己的。
只启动一个服务,最好绑定0.0.0.0:8003,因为0.0.0.0可以接收发给其他两个地址的连接,而其他两个地址都无法接收不等于自己地址的连接(即使只有一个服务)。

由于:

  1. windows 下处于time_wait状态的socket默认就可以快速复用原ip+port,无需进行任何设置。
  2. 无论是否设置SO_REUSEADDR,对于完全相同的ip+port,无论同时有多少个客户端请求连接,只有最先绑定的服务端能接收请求,后面想绑定同样ip+port的服务端要么无法绑定,要么绑定了也接收不到请求(除非最先绑定的服务端已经关闭,不再监听,且客户端重新发起一个新的TCP连接)。
    所以,个人认为在Windows下对服务端socket设置SO_REUSEADDR没什么意义。

在eventlet.listen源码中找到的佐证

API:eventlet.listen
位置:eventlet库中convenience.py的listen函数
在Windows平台上不设置SO_REUSEADDR选项(估计也是因为觉得没意义),Windows不支持SO_REUSEPORT选项。
在这里插入图片描述

参考文档

  1. 浅析套接字中SO_REUSEPORT和SO_REUSEADDR的区别
  2. SO_REUSEADDR与SO_REUSEPORT平台差异性与测试
  3. 如何解决TIME_WAIT过多的解决办法(附Socket中的TIME_WAIT状态详解)
  4. TCP/IP详解–TCP连接中TIME_WAIT状态过多
  5. 服务器端主动关闭连接, 产生的TIME_WAIT状态为什么会占用服务端大量端口?
  6. What is the cost of many TIME_WAIT on the server side?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值