recibir paquetes UDP enviados a 127.0.0.1 cuando se utiliza SO_REUSEADDR

Estoy tratando de hacer que un conjunto de aplicaciones se descubran entre sí mediante UDP y mensajes de difusión. Las aplicaciones enviarán periódicamente un paquete UDP indicando quiénes son y qué pueden hacer. Inicialmente solo usamos para transmitir a INADDR_BROADCAST.

Todas las aplicaciones comparten el mismo puerto para escuchar (de ahí el SO_REUSEADDR). Se adjunta un objeto de kernel de evento al socket, por lo que se nos notifica cuando podemos obtener un nuevo paquete y usarlo en un bucle WaitFor. El socket se utiliza asíncrono.

Apertura del zócalo:

FBroadcastSocket := socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
if FBroadcastSocket = INVALID_SOCKET then Exit;
i := 1;
setsockopt( FBroadcastSocket, SOL_SOCKET, SO_REUSEADDR, Pointer( @i ), sizeof( i ) );
i := 1;
setsockopt( FBroadcastSocket, SOL_SOCKET, SO_BROADCAST, Pointer( @i ), sizeof( i ) );
System.FillChar( A, sizeof( A ), 0 );
A.sin_family      := AF_INET;
A.sin_port        := htons( FBroadcastPort );
A.sin_addr.S_addr := INADDR_ANY;
if bind( FBroadcastSocket, A, sizeof( A ) ) = SOCKET_ERROR then begin
    CloseBroadcastSocket();
    Exit;
end;
WSAEventSelect( FBroadcastSocket, FBroadcastEvent, FD_READ );

Envío de datos a una lista específica de direcciones:

for i := 0 to High( FBroadcastAddr ) do begin
    if sendto( FBroadcastSocket, FBroadcastData[ 0 ], Length( FBroadcastData ), 0, FBroadcastAddr[ i ], sizeof( FBroadcastAddr[ i ] ) ) < 0 then begin
        TLogging.Error( C_S505, [ GetWSAError() ] );
    end;
end;

Recibiendo paquetes:

procedure TSocketHandler.DoRecieveBroadcast();
var
    RemoteAddr:    TSockAddrIn;
    i, N:          Integer;
    NetworkEvents: WSANETWORKEVENTS;
    Buffer:        TByteDynArray;
begin
    // Sanity check.
    FillChar( NetworkEvents, sizeof( NetworkEvents ), 0 );
    WSAEnumNetworkEvents( FBroadcastSocket, 0, @NetworkEvents );
    if NetworkEvents.ErrorCode[ FD_READ_BIT ] <> 0 then Exit;

    // Recieve the broadcast buffer
    i := sizeof( RemoteAddr );
    SetLength( Buffer, MaxUDPBufferSize );
    N := recvfrom( FBroadcastSocket, Buffer[ 0 ], Length( Buffer ), 0, RemoteAddr, i );
    if N <= 0 then begin
        N := WSAGetLastError();
        if N = WSAEWOULDBLOCK then Exit;
        if N = WSAEINTR then Exit;
        TLogging.Error( C_S504, [ GetWSAError() ] );
        Exit;
    end;

    DoProcessBroadcastBuffer( Buffer, N, inet_ntoa( RemoteAddr.sin_addr ) );
end;

Cuando enviamos los datos de difusión utilizando INADDR_BROADCAST, la dirección de difusión local (192.168.1.255) o la dirección de IP local, todo funciona bien. En el momento en que usamos 127.0.0.1 para "transmitir" a, la recepción es esporádica pero generalmente no funciona.

¿Alguien tiene una idea de cómo resolver esto (la lista de direcciones puede cambiarse)? Si todo lo demás falla, buscaré todas las direcciones IP locales y simplemente reemplazaré 127.0.0.1 con eso, pero eso deja problemas cuando cambian las direcciones IP.

Actualización: la primera vez que inicie App1, App1 recibirá paquetes. A continuación se inicia App2. Ahora App1 seguirá recibiendo paquetes, pero App2 no lo hará. Si detienes App1, App2 comenzará a recibir paquetes. Si inicia App3, App2 recibirá sus paquetes, pero App3 no lo hará.

Por lo tanto: solo una aplicación recibirá los paquetes cuando se utilice 127.0.0.1.

Además, configurar IPPROTO_IP, IP_MULTICAST_LOOP en uno con setsocketopt no cambia nada.

Respuestas a la pregunta(1)

Su respuesta a la pregunta