SO_REUSEADDR 与 SO_REUSEPORT 选项

首先一条TCP connection 是由两个 addr-port 的组合组成的

1, 开启 SO_REUSEADDR 可以起到下面4个不同的功能

(1)  即使以前建立的连接还存在,依然可以在这个连接的本地端口号上绑定监听服务器, 通常这个条件通常是这么遇见的 

    1,启动一个服务器, 监听addr1 , port1

    2,新连接到达,fork一个子进程处理这个连接 addr1,port1 ---> addr2, port2

    3,服务器挂了,但此时这个子进程没挂,所以连接 addr1, port1 ---> addr2, port2 还存在

    4, 重启服务器,这个时候存在 port1 上的 TCP连接,但是如果开启了 SO_REUSERADDR, 依旧可以在 port1 上启动监听 socket

 

(2) SO_REUSEADDR  允许在同一端口上启动多个监听socket,只要这些socket监听的ip地址不一样即可 (前提是这个socket设置了SO_REUSEADDR)

  假如我的机器有ip1, ip2, ip3 etc.

  如果利用SO_REUSEADDR, 启了4个socket  fd1, fd2, fd3分别监听 ip1-port1, ip2-port1, INADDR_ANY,那么目的地址为ip1 的连接只能被 fd1

  accept, 同理只有目的地址为ip2 的才会被fd2 accept, 剩下的都被 fd3 accept。

 有的系统规定 ip3 (INADDR_ANY) 只能最后绑定,避免恶意的bind 非 any 的地址,来阻碍以前bind any的socket accept

 即使是设定的SO_REUSEADDR,  对TCP而言搞出来监听同一个ip-port也是不被允许的,这样保证一个新连接只能被一个listenfd accept

 注意这里的启动多个listenfd 是无视进程的,也就是说在一台机器上 bind listenfd都是上面提到的结果

 注意,可以从看到在(1)的情况下,如果之前的服务器没挂,依旧是不能bind的

 

(3)SO_REUSEADDR 使得UDP可以在完全一样的ip-port 绑定多个 socket, 这样如果数据报是多播的话,所有的socket都能拿到一份拷贝,如果是单播,

只有一个能拿到数据报,具体是哪个看系统实现(这个情况在同一个程序启动了多个实例的时候会出现)

 

2, SO_REUSEPORT 作为 SO_REUSEADDR的扩充,有以下作用:

对于TCP,在每个 socket 都同时指定了 SO_REUSEPORT 和 SO_REUSEADDR时,可以绑定完全重复的端口,但是并没有什么理由需要这么做 

对于UDP,SO_REUSEPORT 和 SO_REUSEADDR是等效的

总的来说,就是显式的说明我们的UDP程序需要 “同时启动多个实例”, 并且“一起接收多播数据报”了,虽然这个情况下直接用SO_REUSEADDR也就可以了- -

反正就是个不常用的选项,没事别作就可以了

posted on 2016-05-20 00:17  远近闻名的学渣  阅读(433)  评论(0)    收藏  举报

导航