SO_REUSEADDR和SO_REUSEPORT具体作用是什么详情可以参考这篇文章:
https://www.jianshu.com/p/a23b7e8a4c6a
这里贴一些关键信息:
SO_REUSEADDR
- 作用一
- 在为Socket B设置了SO_REUSEADDR以后,判断冲突的方式就变了。只要地址不是正好(exactly)相同,那么多个Socket就能绑定到同一ip上。比如0.0.0.0和192.168.0.100,虽然逻辑意义上前者包含了后者,但是0.0.0.0泛指所有本地ip,而192.168.0.100特指某一ip,两者并不是完全相同,所以Socket B尝试绑定的时候,不会再报EADDRINUSE,而是绑定成功。
- 作用二
- 绑定TIME_WAIT状态的地址
- 一个非常现实的问题是,假如一个systemd托管的service异常退出了,留下了TIME_WAIT状态的socket,那么systemd将会尝试重启这个service。但是因为端口被占用,会导致启动失败,报错:“Address already in use”,造成两分钟的服务空档期,systemd也可能在这期间放弃重启服务。但是在设置了SO_REUSEADDR以后,处于TIME_WAIT状态的地址也可以被绑定,就杜绝了这个问题。因为TIME_WAIT其实本身就是半死状态,虽然这样重用TIME_WAIT可能会造成不可预料的副作用,但是在现实中问题很少发生,所以也忽略了它的副作用。
SO_REUSEPORT
- SO_REUSEPORT干的其实是大众期望SO_REUSEADDR能够干的事,将多个socket绑定到同一ip和端口。并且它要求所有绑定同一ip/port的socket都设置了SO_REUSEPORT。不过可能有的操作系统并没有这个option。
golang中的实现:
主要是通过golang.org/x/sys/unix包来设置socket属性,有其他包已经做好了兼容各个操作系统的封装 https://github.com/gogf/greuseport
有疑问加站长微信联系(非本文作者)