gpt4 book ai didi

macos - SO_REUSEADDR 和 SO_REUSEPORT 的行为改变了吗?

转载 作者:行者123 更新时间:2023-12-01 23:10:17 27 4
gpt4 key购买 nike

在旧版本的 Mac OS X 中,通配符绑定(bind)的工作方式如下所述:

Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?

Multicast Addresses

The meaning of SO_REUSEADDR changes for multicast addresses as it allows multiple sockets to be bound to exactly the same combination of source multicast address and port. In other words, for multicast addresses SO_REUSEADDR behaves exactly as SO_REUSEPORT for unicast addresses. Actually the code treats SO_REUSEADDR and SO_REUSEPORT identically for multicast addresses, that means you could say that SO_REUSEADDR implies SO_REUSEPORT for all multicast addresses and the other way round.

MacOS X

At its very core, MacOS X is simply a BSD-style UNIX, based on a rather late fork of the BSD code, which was even synchronized with FreeBSD 5 for the Mac OS 10.3 release. That's why MacOS X offers the same options as BSD and they also behave the same way as in BSD.

但是在 10.10.5 中,我在测试网络库时发现了一个变化。

即使设置了 SO_REUSEADDR,两个未绑定(bind)(通配符)UDP 套接字也不能再共享同一端口 (errno=EADDRINUSE)。两者都必须设置 SO_REUSEPORT,这对我来说是个谜。

它可以用这个简单的测试代码重现:

#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

int main() {
for(int p = 0; p < 4; ++p) {
printf("Flags set: ");
if(p&1) printf("SO_REUSEADDR ");
if(p&2) printf("SO_REUSEPORT");
printf("\n");

int handles[2];
bool success = true;
for(int i = 0; i < sizeof(handles)/sizeof(int); ++i) {
handles[i] = socket(AF_INET, SOCK_DGRAM, 0);

int flag = 1;
if((p&1) && setsockopt(handles[i], SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)) == -1) {
printf("Setsockopt %d, SO_REUSEADDR failed with errno\n", i, errno);
success = false;
break;
}
if((p&2) && setsockopt(handles[i], SOL_SOCKET, SO_REUSEPORT, &flag, sizeof(flag)) == -1) {
printf("Setsockopt %d, SO_REUSEPORT failed with errno\n", i, errno);
success = false;
break;
}

struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = 2000; // does not matter as long as it is currently free
addr.sin_addr.s_addr = 0; // wildcard address

if(bind(handles[i], (struct sockaddr*)&addr, sizeof(addr)) == -1) {
printf("Bind %d failed with errno %d\n", i, errno);
success = false;
break;
}
}
if(success)
printf("Alright\n");

for(int i = 0; i < sizeof(handles)/sizeof(int); ++i)
close(handles[i]);
printf("\n");
}

return 0;
}

哪些输出:

Flags set: 
Bind 1 failed with errno 48

Flags set: SO_REUSEADDR
Bind 1 failed with errno 48

Flags set: SO_REUSEPORT
Alright

Flags set: SO_REUSEADDR SO_REUSEPORT
Alright

最佳答案

In older versions of Mac OS X, wildcard binding works like described here:

Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?

Multicast Addresses

您引用的描述适用于多播地址。您的测试代码不使用 multicast address 。因此,适用不同的描述(来自同一来源):

SO_REUSEPORT

SO_REUSEPORT is what most people would expect SO_REUSEADDR to be. Basically, SO_REUSEPORT allows you to bind an arbitrary number of sockets to exactly the same source address and port as long as all prior bound sockets also had SO_REUSEPORT set before they were bound. …

您的测试代码完全证实了这一点。

关于macos - SO_REUSEADDR 和 SO_REUSEPORT 的行为改变了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32661091/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com