双UDP套接字在两个不同的UDP套接字在Linux中
结合在C++中,当我运行(红色警报!伪代码)双UDP套接字在两个不同的UDP套接字在Linux中
bind(s1, <local address:port1234>)
bind(s2, <local address:port1234>)
(s1
和s2
一起socket()
电话每次创建)我得到的问题。在Linux(Ubuntu)中,双重绑定似乎很好。但是,在Windows中,双重绑定失败,并且第二次调用bind()
的地址返回!= 0
。
我想在我的Linux机器上获得Windows上的行为。我可以使用一些设置来获得Linux上的“端口繁忙”吗?
请参阅bind和setsockopt。除非你用SO_REUSEADDR调用了setsockopt,否则你使用相同的地址调用bind应该会导致EADDRINUSE失败。
你是对的钱! SO_REUSEADDR在Windows和Linux(BSD-sockets?)中的工作方式不同。 – 2010-03-05 04:51:48
虽然SO_REUSEADDR不允许您绑定到端点两次。其目的是在关闭TCP套接字后覆盖TIME_WAIT状态。通常,操作系统会在TIME_WAIT中保留一个TCP套接字几分钟来拾取尚未到达的任何“迟到”数据包。如果你尝试打开一个新的套接字,你会得到EADDRINUSE,除非你指定了杀死TIME_WAIT套接字的SO_REUSEADDR。 – 2010-03-05 05:25:43
@ JohnKugelman-实际上并非如此;在Linux和UDP上,SO_REUSEADDR实际上允许您同时绑定到同一端点的多个套接字。这不同于Linux + TCP的语义,也不同于BSD上的语义。 – 2014-01-15 18:04:05
你确定吗?据man 7 ip
在我的Linux机器(Fedora 9中):
当一个进程想要接收新传入的数据包或连接,它应该套接字使用绑定绑定到一个本地接口地址(2)。 只有一个IP套接字可以绑定到任何给定的本地(地址,端口)对。
没有为UDP例外在任一man 7 ip
或man 7 udp
结合的没有提及。 (这不能证明任何事情,但在这种情况下非文件化的行为是......令人惊讶的)。
这不是我在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;
}
对于代码示例(我即将发布一个,但现在不会:-P)的+1,但地址族(即,在“sin_family”字段中)应使用小的nit:AF_INET。 – 2010-03-05 04:51:16
我个人在'socket'调用中也使用了'AF_INET' --- Open Group Base Specification实际上没有任何'PF_ *'常量---但我可以看到更多的“宽松”套接字和其他非地址用法。 – 2010-03-05 04:52:15
正确的你是先生,更新(Linux手册页说,使用'PF_'常量为'socket()'的参数,但我相信没有实际区别)。 – caf 2010-03-05 04:56:41
你能发表真实的代码吗?在你问我之前,我非常确定你*会*在第二次绑定时发生错误。 – 2010-03-05 04:41:58
我也这么认为,所以我测试了它。在socket()调用之后,第二个bind()到同一个端口将返回EADDRINUSE。 – msw 2010-03-05 04:47:35