SO_REUSEPORT,顾名思义端口复用,linux3.9以后才引入
先上官方解释:
Permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address. This option must be set on each socket (including the first socket) prior to calling bind(2) on the socket. To prevent port hijacking, all of the pro‐ cesses binding to the same address must have the same effec‐ tive UID. This option can be employed with both TCP and UDP sockets. For TCP sockets, this option allows accept(2) load distribu‐ tion in a multi-threaded server to be improved by using a dis‐ tinct listener socket for each thread. This provides improved load distribution as compared to traditional techniques such using a single accept(2)ing thread that distributes connec‐ tions, or having multiple threads that compete to accept(2) from the same socket. For UDP sockets, the use of this option can provide better distribution of incoming datagrams to multiple processes (or threads) as compared to the traditional technique of having multiple processes compete to receive datagrams on the same socket.翻译:允许多个 AF_INET or AF_INET6套接字绑定在用一个地址上,这个选项必须在每一个套接字bind之前设置,为了防止端口被截取,所有的进程必须要有相同的UID,这个选项对于TCP和UDP都起作用
对于TCP,这个选项允许accept在多个线程使用,改善了以前只能在一个线程accept,接收成功后再分发到其它线程,或者多个线程竞争accept
对于UDP,我本身不熟悉
个人理解:
SO_REUSEPORT在linux内核3.9以及以后的版本被引入,可以在多个线程或者进程中监听同一个ip和端口组成的套接口,注意在每个线程或者进程都需要单独调用socket创建套接口,bind相同的ip和端口;对于负载均衡,内核应该是有考虑,我简单测试了10次请求,基本上是均匀的分配在所有的监听线程或者进程上。
示例可以参考附件1
SO_REUSEADDR
先上官方解释:
Indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses. For AF_INET sockets this means that a socket may bind, except when there is an active listening socket bound to the address. When the listening socket is bound to INADDR_ANY with a spe‐ cific port then it is not possible to bind to this port for any local address. Argument is an integer boolean flag.
解释:bind应该允许本地地址重用,对于AF_INET套接字,这个指的是一个套接字可以绑定,除非已经有一个正在监听在此地址上的套接口,当一个监听套接口是绑定在INADDR_ANY+port 上,就不能绑定在任何一个本地端口上面
个人理解:
使用SO_REUSEADDR选项后,只要没有在该ip+端口上面的监听套接字(包括但不限于established,timewait),那么就可以bind成功,另看到很多博客写到要在time_wait状态,我测试没有此限制,官方文档也没有提及;一般用在服务器重启,服务器重启时一般情况套接口会处在time_wait,如果不加此选项bind会失败。
对应参考附件2