【问题标题】:SO_EXCLUSIVEADDRUSE and SO_REUSEADDR confusionSO_EXCLUSIVEADDRUSE 和 SO_REUSEADDR 混淆
【发布时间】:2018-04-05 13:07:50
【问题描述】:

(运行于VS2017,Win7 x64)

我对@9​​87654323@ 和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 - 如果我不想让任何人强行绑定到我的端口,我只是不启用SO_REUSEADDR 在那个过程中?

我能看到的唯一区别是,如果我在第一个进程中启用 SO_EXCLUSIVEADDRUSE,然后在第二个进程中尝试绑定,那么第二个绑定将失败

a) WSAEADDRINUSE 如果我在第二个进程中启用 SO_REUSEADDR

b) WSAEACCES 如果我在第二个进程中启用SO_REUSEADDR

所以我尝试在第一个进程中同时启用SO_EXCLUSIVEADDRUSESO_REUSEADDR,但发现无论我第二次尝试的哪个都以WSAEINVAL 失败。

另请注意,我已阅读 this 过去的问题,但上面所说的不是我所看到的:它说明了

具有 SO_REUSEADDR 的套接字始终可以绑定到完全相同的源 地址和端口作为已经绑定的套接字,即使另一个套接字 绑定时没有设置这个选项

如果是这样的话,那么我绝对可以看到SO_EXCLUSIVEADDRUSE 的必要性。

我很确定我做错了什么,但我看不到;有人可以澄清一下吗?

【问题讨论】:

    标签: sockets network-programming winsock winsock2


    【解决方案1】:

    如文档中所述,SO_EXCLUSIVEADDRUSE 在 Windows NT4 SP4 上可用;在此之前只有 SO_REUSEADDR。所以两者的存在都有(也)历史原因。

    我认为 SO_REUSEADDR 是 intent 共享地址(这仅对 UDP 多播真正有用。对于单播或 TCP,它实际上并没有多大作用,因为行为对于两个插座)。

    SO_EXCLUSIVEADDRUSE 是一种安全措施,可避免我的(服务器)应用程序的流量被稍后绑定到同一 IP/端口而被劫持/变得无用。

    在我看来,您需要 SO_REUSEADDR 用于 UDP multicat,并且您需要 SO_EXCLUSIVEADDRUSE 作为服务器应用程序的安全措施。

    【讨论】:

    • 谢谢。但是我还是看不出SO_EXCLUSIVEADDRUSE的意义;如果我没有在我的服务器中设置SO_REUSEADDR,那么即使它本身设置了SO_REUSEADDR,也没有恶意应用程序可以劫持我的流量(如上所示)。因此我不需要SO_EXCLUSIVEADDRUSESO_EXCLUSIVEADDRUSE 给了我什么是我不设置 SO_REUSEADDR 得不到的?
    • 在操作上你是对的,但正如文档所提到的,“排他性”是后来引入的,最重要的是,他们进行了更改以提高安全性。因此,您会得到混合的历史资料(更不用说与 UNIX/Linux 套接字的差异了)。此外,我发现使用“独占”显式增加了代码的可读性......
    • 如果只是在服务器中不设置SO_REUSEADDR 可以防止恶意客户端绑定到同一端口,为什么还要引入SO_EXCLUSIVEADDRUSE?我唯一能想到的是,在早期版本中,不设置 SO_REUSEADDRnot 阻止恶意客户端 - 因此引入 SO_EXCLUSIVEADDRUSE 来解决这个问题 - 而在最近的版本中, SO_REUSEADDR 的行为发生了变化,因此不在服务器中设置它可以防止恶意客户端绑定,因此不需要渲染 SO_EXCLUSIVEADDRUSE。但这在我能找到的任何地方都没有记录,你怎么看?
    • 这在 MSDN(XP 和更早版本)的第二个表中提到:如果第一次绑定是在没有任何选项(“默认”)的情况下完成的,那么第二次(使用 SO_REUSEADDR)会成功。
    • 优秀。我没有发现第二个表适用于 XP 和更早版本(因此我不会在我的 Win7 机器上看到这种行为),而第三个表适用于 Server 2003 及更高版本。谢谢!
    猜你喜欢
    • 2016-07-11
    • 2013-03-20
    • 2023-03-03
    • 2021-04-10
    • 2021-11-06
    • 2011-12-04
    • 2016-01-12
    • 2013-01-02
    • 2018-06-01
    相关资源
    最近更新 更多