Как отправить сообщение и получить ответ на одном сокете - PullRequest
4 голосов
/ 23 февраля 2012

У меня есть следующий код, который отправляет многоадресное сообщение, а затем ожидает ответа на адрес, с которого пришло сообщение. Если я наблюдаю за трафиком в Wireshark, я вижу, что сообщение отправляется нормально, и ответ возвращается на правильный IP-адрес и порт, однако сокет никогда не возвращается из линии приема, как будто ответ не принимается.

    var multicastAddress = IPAddress.Parse("239.255.255.250");
    var multicastPort = 1900;
    var unicastPort = 1901;        

    using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
    {
        socket.Bind(new IPEndPoint(IPAddress.Any, unicastPort));
        socket.Connect(new IPEndPoint(multicastAddress, multicastPort));
        var thd = new Thread(() =>
             {
                 try
                 {
                     while (true)
                     {
                         var response = new byte[8000];
                         EndPoint ep = new IPEndPoint(IPAddress.Any, unicastPort);
                         socket.ReceiveFrom(response, ref ep);
                         var str = Encoding.UTF8.GetString(response);
                         Devices.Add(new SsdpDevice() {Location = str});
                     }
                 }
                 catch
                 {
                     //TODO handle exception for when connection closes
                 }
             });
        socket.Send(broadcastMessage, 0, broadcastMessage.Length, SocketFlags.None);
        thd.Start();
        Thread.Sleep(30000);
        socket.Close();
    }

Я знаю, что должен использовать асинхронные методы в классе сокетов и должен прекратить полагаться на Thread.Sleep, но я просто хочу получить простой пример работы, прежде чем привести в порядок код.

1 Ответ

9 голосов
/ 24 февраля 2012

Гэвин, проверьте это:

  • Не используйте разные порты.Как вы ожидаете многоадресную рассылку на одном и прием на другом?
  • Не используйте Connect(), многоадресная рассылка - это обмен сообщениями без установления соединения (так же, как широковещательная рассылка).
  • Установите параметр сокета для многоадресной рассылки послеBind().
  • Используйте SendTo() вместо Send(), что не сработает в этом случае.
  • Первый запуск приема (даже в режиме блокировки, это другая конечная точка),затем отправьте.

И простой рабочий пример:

var broadcastMessage = Encoding.UTF8.GetBytes("Hello multicast!");
var multicastAddress = IPAddress.Parse("239.255.255.250");
var signal = new ManualResetEvent(false);
var multicastPort = 1900;

using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
{
    var multicastEp = new IPEndPoint(multicastAddress, multicastPort);
    EndPoint localEp = new IPEndPoint(IPAddress.Any, multicastPort);

    // Might want to set this:
    //socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); 
    socket.Bind(localEp);
    socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastAddress, IPAddress.Any));
    // May want to set this:
    //socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 0); // only LAN
    var thd = new Thread(() =>
        {
            var response = new byte[8000];
            socket.ReceiveFrom(response, ref localEp);
            var str = Encoding.UTF8.GetString(response).TrimEnd('\0');
            Console.WriteLine("[RECV] {0}", str);
            signal.Set();
            Console.WriteLine("Receiver terminating...");
        });
    signal.Reset();
    thd.Start();

    socket.SendTo(broadcastMessage, 0, broadcastMessage.Length, SocketFlags.None, multicastEp);
    Console.WriteLine("[SEND] {0}", Encoding.UTF8.GetString(broadcastMessage));
    signal.WaitOne();
    Console.WriteLine("Multicaster terminating...");
    socket.Close();
    Console.WriteLine("Press any key.");
    Console.ReadKey();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...