在旧版本的Mac OS X中,通配符绑定的工作方式如下所述:
多播地址SO_REUSEADDR的含义会更改多播地址,因为它允许将多个套接字绑定到源多播地址和端口的完全相同的组合 . 换句话说,对于多播地址,SO_REUSEADDR的行为与单播地址的SO_REUSEPORT完全相同 . 实际上,代码对于多播地址同样对待SO_REUSEADDR和SO_REUSEPORT,这意味着您可以说SO_REUSEADDR对所有多播地址都意味着SO_REUSEPORT,反之亦然 .
和
MacOS X在其核心,MacOS X只是一个BSD风格的UNIX,基于BSD代码的相当晚的分支,甚至与Mac OS 10.3版本的FreeBSD 5同步 . 这就是为什么MacOS X提供与BSD相同的选项,它们的行为方式与BSD相同 .
但在10.10.5中,我在测试网络库时发现了一个变化 .
即使设置了SO_REUSEADDR,两个未绑定(通配符)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
1 回答
您引用的描述适用于多播地址 . 您的测试代码不使用multicast address . 因此,适用不同的描述(来自同一来源):
您的测试代码确切地证实了这一点 .