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 套接字上(s1
和 s2
每个都是通过调用 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 ip
或man 7 udp
中都没有提到UDP 绑定的异常。 (这并不能证明任何事情,但在这种基本的事情中没有记录的行为......令人惊讶。)
【讨论】:
以上是关于Linux中的双UDP套接字绑定的主要内容,如果未能解决你的问题,请参考以下文章