Приложение My Winsock Delphi должно прослушивать все сетевые интерфейсы для многоадресного потока UDP/IP. Он слушал нормально, пока я не попробовал его на другом ПК с приоритетным порядком разных сетевых адаптеров.Разница между INADDR_ANY в Linux и программировании сокетов Windows
Тогда я начал задачи исследования и на некоторых форумах, что INADDR_ANY
(или 0.0.0.0
) имеет разное значение в ОС Windows и Linux:
- В Linux it means "listen on all interfaces" и для отправки - отправить через интерфейс по умолчанию
- В Windows it means "listen on default interface" (
0.0.0.1
для второго). Образец цитирования: «Если этот член указывает IPv4-адрес 0.0.0.0, используется интерфейс многоадресной передачи по IPv4 по умолчанию» - без упоминания о том, предназначено ли оно для прослушивания или для отправки.
Не могли бы вы подтвердить или опровергнуть это?
Как слушать действительно на всех интерфейсах?
Вот маленький кусочек моего кода:
TMulticastListener = class(TThread)
private
mreq: ip_mreq;
............
end;
constructor TMulticastListener.Create;
var err: Integer;
wData: WsaData;
reuse: Integer;
begin
inherited Create(true);
err := WSAStartup(MAKEWORD(2, 2), wData);
if err = SOCKET_ERROR then begin
// Tell the user that we could not find a usable Winsock DLL
perror('WSAStartup');
Exit;
end;
// create what looks like an ordinary UDP socket
fd := socket(AF_INET, SOCK_DGRAM, 0);
if fd = INVALID_SOCKET then begin
perror('socket');
Exit;
end;
reuse := 1;
// allow multiple sockets to use the same PORT number
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, Pointer(@reuse), SizeOf(reuse)) < 0) then begin
perror('Reusing ADDR failed');
Exit;
end;
// set up destination address
FillChar(addr, sizeof(addr), 0);
addr.sin_family := AF_INET;
addr.sin_addr.s_addr := htonl(INADDR_ANY); // N.B.: differs from sender
addr.sin_port := htons(HELLO_PORT);
// bind to receive address
if (bind(fd, addr, sizeof(addr)) < 0) then begin
perror('bind');
Exit;
end;
// use setsockopt() to request that the kernel join a multicast group
mreq.imr_multiaddr.s_addr := inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr := htonl(INADDR_ANY); //inet_addr('0.0.0.0');
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, @mreq, sizeof(mreq)) < 0) then begin
perror('setsockopt');
Exit;
end;
end;
Спасибо. Я предоставил полный код. Будут читать ваши дома. – Paul