当前位置:  开发笔记 > 程序员 > 正文

使用SO_REUSEADDR时,接收UDP数据包发送到127.0.0.1

如何解决《使用SO_REUSEADDR时,接收UDP数据包发送到127.0.0.1》经验,为你挑选了0个好方法。

我试图使一组应用程序使用UDP和广播消息发现彼此.应用程序将定期发送一个UDP数据包,说明它们是谁以及它们可以做什么.最初我们只用于广播到INADDR_BROADCAST.

所有应用程序共享同一个端口进行监听(因此SO_REUSEADDR).事件内核对象附加到套接字,因此当我们可以获取新数据包并在WaitFor循环中使用它时,我们会收到通知.套接字用于异步.

打开插座:

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 );

将数据发送到指定的地址列表:

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;

接收包:

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;

当我们使用INADDR_BROADCAST发送广播数据时,本地广播地址(192.168.1.255)或本地IP地址一切正常.我们使用127.0.0.1"广播"的那一刻,接收是零星的,但一般不起作用.

有没有人知道如何解决这个问题(地址列表是可变的)?如果所有其他方法都失败了,我将查找所有本地IP地址,并将其替换为127.0.0.1,但在IP地址更改时会出现问题.

更新:首次启动App1时,App1将收到数据包.接下来启动App2.现在App1仍然会收到数据包,但App2不会.如果您停止App1,App2将开始接收数据包.如果您启动App3,App2将收到它的数据包,但App3不会.

因此:当使用127.0.0.1时,只有一个应用程序将接收数据包.

使用setsocketopt将IPPROTO_IP,IP_MULTICAST_LOOP设置为1也不会改变任何内容.

推荐阅读
郑谊099_448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有