Многоадресная рассылка UDP между двумя сокетами в одном процессе

Я пишу несколько тестов для классов, которые обрабатывают многоадресную связь UDP. Я разработал тесты для использования интерфейса loopback (127.0.0.1 )для тестов, потому что я не хочу, чтобы они мешали другим программам/устройствам в сети.

В моем «модульном тесте» у меня есть проверенный сокет, который присоединяется к данной группе многоадресной рассылки и привязывается к 127.0.0.1 и отправителю. сокет, который также присоединился к той же группе многоадресной рассылки и привязывается к 127.0.0.1, оба, конечно, в одном и том же процессе.

Чтобы убедиться, что сообщение отправлено, у меня есть еще одна тестовая программа (, а значит, еще один процесс ), который также присоединяется к группе многоадресной рассылки и выводит все, что ей отправляется.

Проблема в том, что мой проверенный сокет никогда не получает то, что отправил отправитель, НО тестовая программа (, поэтому другой процесс )получает это.

Есть ли какие-то ограничения на комбинацию нескольких сокетов/многоадресной рассылки/локального хоста?

Новая информация:

Моей ошибкой было считать, что UDP на локальном хосте может быть надежным. Приведенная ниже тестовая программа показывает, что первый UDP-пакет никогда не был получен (, по крайней мере, на моем компьютере )моим прослушивающим сокетом (, но другой процесс все еще получает его ).

В своих модульных тестах я отправляю один пакет и ожидаю конкретных ответов :Я не могу отправить сообщение два раза и получить ответ только один раз.

Кажется, он работает надежно, если я жду первого тайм-аута приема перед отправкой первого пакета.

Кто-нибудь знает, почему первый пакет UDP никогда не приходит?

Вот код, который я использовал в своих испытаниях:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using NUnit.Framework;

namespace MulticastTest
{
    [TestFixture]
    public class Program
    {
        static void Main(string[] args)
        {
            new Program().Run();
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }

    [Test]
    public void Run()
    {
        _waitFirstReadTiemout = new AutoResetEvent(false);
        IPAddress lMulticastAddress = new IPAddress(0xFAFFFFEF);
        IPEndPoint lRemoteEndPoint = new IPEndPoint(lMulticastAddress, 1900);

        // Create sender socket
        Socket lSendSocket = new Socket(AddressFamily.InterNetwork,
                             SocketType.Dgram,
                             ProtocolType.Udp);

        // Allow to share the port 1900 with other applications
        lSendSocket.SetSocketOption(SocketOptionLevel.Socket,
                                SocketOptionName.ReuseAddress,
                                true);

        // Set TTL for multicast packets: socket needs to be bounded to do this
        lSendSocket.SetSocketOption(SocketOptionLevel.IP,
                                SocketOptionName.MulticastTimeToLive,
                                2);

        // Bind the socket to the local end point: this MUST be done before joining the multicast group
        lSendSocket.Bind(new IPEndPoint(IPAddress.Loopback, 55236));

        // Join the multicast group
        lSendSocket.SetSocketOption(SocketOptionLevel.IP,
                        SocketOptionName.MulticastLoopback,
                        true);

        lSendSocket.SetSocketOption(SocketOptionLevel.IP,
                                SocketOptionName.AddMembership,
                                new MulticastOption(lMulticastAddress));

        // Create receiver and start its thread
        Thread lReceiveThread = new Thread(ReceiveThread);
        lReceiveThread.Start();

        int i = 0;
        while (!fStop)
        {
            if (i == 0)
                _waitFirstReadTiemout.WaitOne(10000);

            byte[] lToSend = Encoding.ASCII.GetBytes(DateTime.Now.ToString("yyyyMMdd HHmmss"));
            lSendSocket.SendTo(lToSend, lRemoteEndPoint);
            Console.WriteLine("Sent #" + (i + 1) + ": " + DateTime.Now.ToString("yyyyMMdd HHmmss"));
            Thread.Sleep(1000);
            try
            {
                if (Console.KeyAvailable || i >= 10)
                    fStop = true;
            }
            catch (InvalidOperationException)
            {
                fStop = i >= 10;
            }
            finally
            {
                ++i;
            }
        }
    }

    private AutoResetEvent _waitFirstReadTiemout;

    private bool fStop;

    private void ReceiveThread()
    {
        Socket lSocket = new Socket(AddressFamily.InterNetwork, 
                                    SocketType.Dgram, 
                                    ProtocolType.Udp);

        // Allow to share the port 1900 with other applications
        lSocket.SetSocketOption(SocketOptionLevel.Socket,
                                SocketOptionName.ReuseAddress,
                                true);

        // TTL not required here: we will only LISTEN on the multicast socket
        // Bind the socket to the local end point: this MUST be done before joining the multicast group
        lSocket.Bind(new IPEndPoint(IPAddress.Loopback, 1900));

        // Join the multicast group

        // If the local IP is a loopback one, enable multicast loopback
        lSocket.SetSocketOption(SocketOptionLevel.IP,
                    SocketOptionName.MulticastLoopback,
                    true);

        lSocket.SetSocketOption(SocketOptionLevel.IP,
                                SocketOptionName.AddMembership,
                                new MulticastOption(
                                        new IPAddress(0xFAFFFFEF)));

        lSocket.ReceiveTimeout = 1000;

        byte[] lBuffer = new byte[65000];
        int i = 0;
        while (!fStop)
        {
            try
            {
                int lReceived = lSocket.Receive(lBuffer);
                ++i;
                Console.WriteLine("Received #" + i + ": " + Encoding.ASCII.GetString(lBuffer, 0, lReceived));
            }
            catch (SocketException se)
            {
                _waitFirstReadTiemout.Set();
                Console.WriteLine(se.ToString());
            }
        }
    }
}

}

5
задан Bruno Knittel 6 August 2012 в 12:13
поделиться