(在VS2017上运行,Win7 x64)
我对SO_REUSEADDR
和SO_EXCLUSIVEADDRUSE
的观点感到困惑。是的,我读过MSDN documentation,但我显然没有得到它。
我在两个单独的进程中有以下简单代码。正如预期的那样,因为我在两个套接字上都启用了SO_REUSEADDR
,所以第二个进程的绑定成功。 如果我没有在这些套接字中的任何一个上启用此功能,则第二个绑定将不会成功。
#define PORT 5150
SOCKET sockListen;
if ((sockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n", WSAGetLastError());
return 1;
}
int optval = 1;
if (setsockopt(sockListen, SOL_SOCKET, `SO_REUSEADDR`, (char*)&optval, sizeof(optval)) == -1)
return -1;
SOCKADDR_IN InternetAddr;
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = inet_addr("10.15.20.97");
InternetAddr.sin_port = htons(PORT);
if (::bind(sockListen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
{
printf("bind() failed with error %d\n", WSAGetLastError());
return 1;
}
所以不必为两个套接字启用SO_REUSEADDR
使SO_EXCLUSIVEADDRUSE
不必要 - 如果我不希望任何人强行绑定到我的端口,我只是不启用{{1}在那个过程中?
我能看到的唯一区别是,如果我在第一个进程中启用SO_REUSEADDR
,那么在第二个进程中尝试绑定,第二个绑定将失败
a)SO_EXCLUSIVEADDRUSE
如果我 在第二个过程中启用WSAEADDRINUSE
b)SO_REUSEADDR
如果我在第二个过程中启用WSAEACCES
所以我尝试在第一个过程中同时启用SO_REUSEADDR
和SO_EXCLUSIVEADDRUSE
,但发现我尝试的第二个过程失败了SO_REUSEADDR
。
另请注意,我已阅读this过去的问题,但所说的不是我所看到的:它说明了
具有SO_REUSEADDR的套接字始终可以绑定到完全相同的源 地址和端口作为已绑定的套接字,即使是另一个套接字 绑定时没有设置此选项
现在如果是这种情况,那么我绝对可以看到WSAEINVAL
的需要。
我很确定我做错了什么但我看不到它;有人可以澄清吗?
答案 0 :(得分:1)
如文档中所述,SO_EXCLUSIVEADDRUSE在Windows NT4 SP4上可用;之前有仅 SO_REUSEADDR。因此,两者都存在(也)历史原因。
我认为SO_REUSEADDR是意图来共享一个地址(这对于UDP多播非常有用。对于单播或TCP,由于bahaviour是非确定性的,所以它确实没有用。两个插座)。
SO_EXCLUSIVEADDRUSE是一个安全措施,以避免我的(服务器)应用程序的流量被以后绑定到同一IP /端口而被劫持/渲染无用。
在我看来,你需要 SO_REUSEADDR用于UDP多播,而你需要 SO_EXCLUSIVEADDRUSE作为服务器应用程序的安全措施。