Обзор. Я настроил сервер и клиент, где оба пытаются обнаружить друг друга с помощью UDP. Когда сервер запускается, он отправляет многоадресное сообщение (239.1.1.1) о том, что он активен. Когда клиент запускается, он отправляет многоадресное сообщение (239.1.1.2) о том, что он активен. И сервер, и клиент подписаны на многоадресные сообщения друг друга для получения своих передач. Таким образом, независимо от того, какое приложение (сервер или клиент) запускается первым, одно или другое будет уведомлено об их существовании.
На стороне клиента я делаю следующее:
- Настройте прослушивающий сокет для подписки и получения многоадресных сообщений от сервера.
- Настройте принимающий сокет для получения ответов сервера на многоадресное
сообщение клиента согласно пункту 3 ниже. - Отправьте сообщение многоадресной рассылки (чтобы сервер получил и ответил), что клиент работает.
- Получите ответ сервера на многоадресное сообщение клиентов, отправленное в # 3.
Вопрос: Все работает нормально, за исключением того, что оба принимающих сокета в конечном итоге получают ответ сервера (без многоадресной рассылки) клиенту. Я не понимаю, ожидаемое это поведение или нет. Могу ли я уменьшить два приемных гнезда до одного? №1 подписан на многоадресную рассылку сервера, а №2 просто прослушивает прямую передачу с сервера на тот же порт (сообщение без многоадресной рассылки с сервера). Могу ли я безопасно удалить вторую приемную розетку?
См. Исходный код ниже (я удалил обработку исключений для упрощения представления кода).
Код клиента:
// 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);
Код сервера:
// 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);