On older versions of Mac OS X, wildcard binding works as described here:
Socket parameters SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same thing on all major operating systems?
Multicast addresses
The SO_REUSEADDR value is changed for multicast addresses, as it allows multiple sockets to bind to the exact same combination of source multicast address and port. In other words, for multicast addresses, SO_REUSEADDR behaves exactly like SO_REUSEPORT for unicast addresses. Actually, the code handles SO_REUSEADDR and SO_REUSEPORT the same for multicast addresses, which means you can say that SO_REUSEADDR means SO_REUSEPORT for all multicast addresses and vice versa.
and
MacOS x
At its core, MacOS X is simply BSD-style UNIX, based on a rather late version of BSD code that was even synced with FreeBSD 5 for Mac OS 10.3. This is why MacOS X offers the same options as BSD, and they also behave the same as in BSD.
10.10.5 , .
() UDP (errno = EADDRINUSE), SO_REUSEADDR.
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;
addr.sin_addr.s_addr = 0;
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