Linux中的双UDP套接字绑定

Posted

技术标签:

【中文标题】Linux中的双UDP套接字绑定【英文标题】:Double UDP socket binding in Linux 【发布时间】:2010-03-05 04:30:31 【问题描述】:

在 C++ 中,当我运行时(红色警报!伪代码)

bind(s1, <local address:port1234>)
bind(s2, <local address:port1234>)

在两个不同的 UDP 套接字上(s1s2 每个都是通过调用 socket() 创建的)我遇到了问题。在 Linux (Ubuntu) 中,双重绑定似乎没问题。然而,在 Windows 中,双重绑定失败,对同一地址的第二次调用 bind() 返回 != 0

我想在我的 Linux 机器上获得我在 Windows 上的行为。是否有一些设置可以让 Linux 上的“端口繁忙”?

【问题讨论】:

你能贴出真实的代码吗?直到你问我很确定你在第二次绑定时确实会出错。 我也是这么想的,所以我测试了一下。在 socket() 调用之后,第二个 bind() 到同一端口返回 EADDRINUSE。 【参考方案1】:

请参阅bind 和setsockopt。除非您使用 SO_REUSEADDR 调用了 setsockopt,否则使用相同地址调用 bind 应该会导致 EADDRINUSE 失败。

【讨论】:

你是对的! SO_REUSEADDR 在 Windows 和 Linux(BSD 套接字?)中的工作方式不同。 SO_REUSEADDR 不允许您绑定到端点两次。其目的是在您关闭 TCP 套接字后覆盖 TIME_WAIT 状态。通常,操作系统会在 TIME_WAIT 中保留一个 TCP 套接字几分钟,以获取尚未到达的任何“迟到的”数据包。如果你尝试打开一个新的套接字,你会得到 EADDRINUSE,除非你指定了 SO_REUSEADDR,它会杀死 TIME_WAIT 套接字。 @JohnKugelman- 实际上不是真的;在 Linux 和 UDP 上,SO_REUSEADDR 实际上确实允许您同时将多个套接字绑定到同一个端点。这不同于Linux+TCP的语义,也不同于BSD的语义。【参考方案2】:

这不是我在 Linux 上的行为。当我运行以下测试程序时,第二个bind 调用失败并显示EADDRINUSE

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main()

    int s1, s2;
    struct sockaddr_in sa = 
        .sin_family = AF_INET,
        .sin_port = 0x5555,
        .sin_addr.s_addr = INADDR_ANY ;

    s1 = socket(PF_INET, SOCK_DGRAM, 0);
    s2 = socket(PF_INET, SOCK_DGRAM, 0);
    if (bind(s1, (struct sockaddr *)&sa, sizeof sa) < 0)
        perror("bind 1");
    if (bind(s2, (struct sockaddr *)&sa, sizeof sa) < 0)
        perror("bind 2");

    return 0;

【讨论】:

+1 用于代码示例(我正要发布一个,但现在不会:-P),但一个小的 nit:AF_INET 应该用于地址系列(即,在sin_family 字段)。 我个人在socket 调用中也使用AF_INET——开放组基本规范实际上没有任何PF_* 常量——但我可以看到更多的案例对于socket 和其他非地址用法的“宽大处理”。 对,先生,更新了(Linux 手册页说使用 PF_ 常量作为 socket() 的参数,但我确信没有实际区别)。【参考方案3】:

你确定吗?根据我的 Linux 机器(fedora 9)上的man 7 ip

当一个进程想要接收新的传入数据包或连接时,它应该使用 bind(2) 将套接字绑定到本地接口地址。 只有一个 IP 套接字可以绑定到任何给定的本地(地址、端口)对。

man 7 ipman 7 udp 中都没有提到UDP 绑定的异常。 (这并不能证明任何事情,但在这种基本的事情中没有记录的行为......令人惊讶。)

【讨论】:

以上是关于Linux中的双UDP套接字绑定的主要内容,如果未能解决你的问题,请参考以下文章

【奇】udp的recvfrom

重新绑定 UDP 套接字

绑定多播 (UDP) 套接字是啥意思?

udp 套接字发送到隐式绑定

使用 C 绑定到 IOCP 的 UDP 套接字

Linux-UDP编码接口以及代码实现