2010-03-05 106 views
0

结合在C++中,当我运行(红色警报!伪代码)双UDP套接字在两个不同的UDP套接字在Linux中

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

s1s2一起socket()电话每次创建)我得到的问题。在Linux(Ubuntu)中,双重绑定似乎很好。但是,在Windows中,双重绑定失败,并且第二次调用bind()的地址返回!= 0

我想在我的Linux机器上获得Windows上的行为。我可以使用一些设置来获得Linux上的“端口繁忙”吗?

+1

你能发表真实的代码吗?在你问我之前,我非常确定你*会*在第二次绑定时发生错误。 – 2010-03-05 04:41:58

+3

我也这么认为,所以我测试了它。在socket()调用之后,第二个bind()到同一个端口将返回EADDRINUSE。 – msw 2010-03-05 04:47:35

回答

4

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

+0

你是对的钱! SO_REUSEADDR在Windows和Linux(BSD-sockets?)中的工作方式不同。 – 2010-03-05 04:51:48

+0

虽然SO_REUSEADDR不允许您绑定到端点两次。其目的是在关闭TCP套接字后覆盖TIME_WAIT状态。通常,操作系统会在TIME_WAIT中保留一个TCP套接字几分钟来拾取尚未到达的任何“迟到”数据包。如果你尝试打开一个新的套接字,你会得到EADDRINUSE,除非你指定了杀死TIME_WAIT套接字的SO_REUSEADDR。 – 2010-03-05 05:25:43

+0

@ JohnKugelman-实际上并非如此;在Linux和UDP上,SO_REUSEADDR实际上允许您同时绑定到同一端点的多个套接字。这不同于Linux + TCP的语义,也不同于BSD上的语义。 – 2014-01-15 18:04:05

0

你确定吗?据man 7 ip在我的Linux机器(Fedora 9中):

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

没有为UDP例外在任一man 7 ipman 7 udp结合的没有提及。 (这不能证明任何事情,但在这种情况下非文件化的行为是......令人惊讶的)。

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; 
} 
+0

对于代码示例(我即将发布一个,但现在不会:-P)的+​​1,但地址族(即,在“sin_family”字段中)应使用小的nit:AF_INET。 – 2010-03-05 04:51:16

+0

我个人在'socket'调用中也使用了'AF_INET' --- Open Group Base Specification实际上没有任何'PF_ *'常量---但我可以看到更多的“宽松”套接字和其他非地址用法。 – 2010-03-05 04:52:15

+0

正确的你是先生,更新(Linux手册页说,使用'PF_'常量为'socket()'的参数,但我相信没有实际区别)。 – caf 2010-03-05 04:56:41