首页 文章

为什么订阅多播组的UDP套接字正在拾取非多播消息?

提问于
浏览
0

Overview: 我已经设置了服务器和客户端,两者都尝试使用UDP发现彼此 . 当服务器启动时,它会发送一个它正在运行的多播消息(239.1.1.1) . 当客户端启动时,它会发送一个它正在运行的多播消息(239.1.1.2) . 服务器和客户端都订阅彼此的多播消息以接收它们的传输 . 这样,无论哪个应用程序(服务器或客户端)首先启动,都将通知其中一个或另一个应用程序存在 .

在客户端,我执行以下操作:

  • 设置侦听套接字以订阅和接收服务器发起的多播消息 .

  • 设置接收套接字以接收服务器对客户端多播的响应
    每个#3下面的消息 .

  • 发送客户端正在运行的muticast消息(供服务器接收和响应) .

  • 接收服务器对#3中发送的客户端多播消息的响应 .

Question: 一切正常,除了两个接收套接字最终获得服务器's (non-multicast) response to the client. I am not clear if this is expected behavior or not. Can I reduce the two receiving sockets to one? #1 is subscribed to the server's多播,#2只是监听来自同一端口上的服务器的直接传输(来自服务器的非多播消息) . 我可以安全地拆下第二个接收插座吗?

请参阅下面的源代码(我删除了异常处理,以简化代码演示) .

Client code:

// 1. Set up a socket and asynchronously listen for server startup multicasts.
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
listenSocket.SetSocketOption(SocketOptionLevel.Socket,
    SocketOptionName.ReuseAddress, 1);
listenSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
listenSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,
    new MulticastOption(IPAddress.Parse("239.1.1.1")));
EndPoint clientEndPoint = new IPEndPoint(0, 0);
listenSocket.BeginReceiveFrom(receiveBuffer, 0, receiveBuffer.Length,
    SocketFlags.None, ref clientEndPoint,
    new AsyncCallback(OnServerMessageReceived), (object)this);

// 2. Set up socket to receive the server's response to client's multicast.
Socket receiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
receiveSocket.SetSocketOption(SocketOptionLevel.Socket,
    SocketOptionName.ReuseAddress, 1);
receiveSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
receiveSocket.ReceiveTimeout = 3000; // Timeout after 3 seconds.

// 3. Send a multicast message for server to respond to.
Socket sendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
EndPoint multicastEndPoint = new IPEndPoint(IPAddress.Parse("239.1.1.2"), 50000);
sendSocket.SendTo(packet, packet.Length, SocketFlags.None, multicastEndPoint);

// 4. Wait for server to respond to the multicast message (timeout = 3 seconds).
byte[] receiveBuff = new byte[2048];
EndPoint serverEndPoint = new IPEndPoint(0, 0);
int bytesRead = receiveSocket.ReceiveFrom(receiveBuff, ref serverEndPoint);

Server code:

// Receive multicast message sent from client (in asynchronous callback method).
EndPoint clientEndPoint = new IPEndPoint(0, 0);
int bytesRead = listenSocket.EndReceiveFrom(asyncResult, ref clientEndPoint);

// Send response back to the client (change port to 50000).
EndPoint destination = new IPEndPoint((clientEndPoint as IPEndPoint).Address,
    50000);
Socket responseSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
    ProtocolType.Udp);
responseSocket.SendTo(response, response.Length, SocketFlags.None, destination);

4 回答

  • 0

    你的问题的答案是“是的,这是预期的行为” . 您无需打开单独的套接字即可在同一端口上接收单播数据包 .

    PS

    让您的服务器加入多播组以侦听新客户端似乎有点过分 - 您可以让服务器定期将信标发送到客户端多播地址,说“我在这里”(例如,每30秒一次) .

  • 3
    receiveSocket.Bind(new IPEndPoint(IPAddress.Any, 50000));
    

    您的接收套接字绑定到任何地址,这意味着它们将接收单播,广播和多播流量 . 您可以绑定到接口地址以仅接收单播流量,并且只能绑定到多播组以仅接收多播流量 .

    发送UDP数据报时,您可以指定可以是多播或单播的目标地址 . 因此,您可以将服务器和客户端代码分别减少到一个套接字 .

  • 2

    虽然我正在解决您的问题,但我希望客户端和服务器能够在相同的IP多播地址(例如239.1.1.1)上进行通信 . 目前,您似乎已经为客户端和服务器分别提供了一个地址,以及当您引入新客户端时会发生什么?

  • 0

    更好的选择是使用像BonjourAvahi这样的服务发现协议,而不是滚动自己的服务,因为它们已经解决了很多问题 .

相关问题