C#:套接字-组播,未接收到数据,未调用BeginReceive / BeginReceiveFrom回调

问题描述 投票:2回答:1

我实际上很茫然,现在有一段时间了。我搜索了Stackoverflow,但找不到解决方案。

问题如下:我没有收到任何数据,并且从未调用过来自Socket(多播)的BeginReceive或BeginReceiveFrom的Callback,并且从未处理过数据,而且我似乎也找不到原因。我看不见树木的森林:(

如果我逐步调试应用程序,有时会收到数据,有时不会。如果我在没有断点的情况下进行调试,并且没有“逐步”进行调试,则它永远不会起作用。

当我用wireshark嗅探多播地址时,我可以看到包到达了,并且我知道包是每500毫秒由服务器发送一次。

这里是单元测试程序和套接字初始化,连接和接收的代码。

也许有人可以帮助我找到错误或为我指明正确的方向...

这是我初始化套接字的方式:

public void Initialize()
{
    IPAddress multicastIP = IPAddress.Parse(mcastConfig.RemoteIPAddress);
    IPAddress localIP = IPAddress.Parse(mcastConfig.LocalIPAddress);

    _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

    _socket.SetSocketOption(SocketOptionLevel.Udp, SocketOptionName.NoDelay, 1);
    _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

    IPEndPoint localEP = new IPEndPoint(localIP, mcastConfig.RemotePort);

    _socket.Bind(localEP);

    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 5);

    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)localIP.Address);

    multicastEndPoint = new IPEndPoint(multicastIP, mcastConfig.RemotePort);

    MulticastOption mcastOption = new MulticastOption(multicastIP, localIP);

    _socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);

    Connect();
}

AsyncConnect运行正常,看起来像这样:

public void Connect()
{

    if (!Connected)
    {
        _socket.BeginConnect(multicastEndPoint, new AsyncCallback(ConnectCallback), _socket);

        connectDone.WaitOne();
        Connected = true;
    }
}

private static void ConnectCallback(IAsyncResult ar)
{
    try
    {
        Socket client = (Socket)ar.AsyncState;

        client.EndConnect(ar);

        connectDone.Set();
    }
    catch (Exception e)
    {
        _log.Error("### Error with the Connection: {0}", e.ToString());
    }
}

问题从BeginReceive开始,它被调用一次,但是什么也没有发生,并且仅当套接字关闭时才调用回调本身(应该是,这里已经读过了):

public void Receive()
{

    byte[] data = new byte[_buffer.Length];

    if (!Connected)
    {
        Connect();
    }

    try
    {
        mcastEP = multicastEndPoint;

        IPAddress localIP = IPAddress.Parse(mcastConfig.LocalIPAddress);
        EndPoint localEP = new IPEndPoint(localIP, mcastConfig.RemotePort);

        _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
        //_socket.BeginReceiveFrom(_buffer, 0, _buffer.Length, SocketFlags.None, ref localEP, new AsyncCallback(ReceiveCallback), _socket);

        Array.Copy(_buffer, data, _buffer.Length);

        pDUHelper.ProcessData(data); //This processes the data and sends an event if the data was correct received
    }
    catch (SocketException se)
    {
        _log.Error("### SocketException ErrorCode: {0}, see: https://support.microsoft.com/en-us/help/819124/windows-sockets-error-codes-values-and-meanings", se.ErrorCode.ToString());
    }
    catch(Exception e)
    {
        _log.Error(e);
    }
}

private void ReceiveCallback(IAsyncResult ar)
{
    Socket socket = ar.AsyncState as Socket;
    IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);
    EndPoint ep = ipep;

    try
    {
        int reicevedBytes = _socket.EndReceive(ar);
        //int reicevedBytes = _socket.EndReceiveFrom(ar, ref ep);

        ipep = ep as IPEndPoint;

        if(reicevedBytes > 0)
        {
            byte[] data = new byte[reicevedBytes];
            Array.Copy(_buffer, data, reicevedBytes);

            pDUHelper.ProcessData(data); //This processes the data and sends an event if the data was correct received

            receiveDone.Set();
        }
    }
    catch (ObjectDisposedException ode)
    {
        _log.Error(ode);
    }
    catch (SocketException se)
    {
        _log.Error(se);
    }
    catch(Exception e)
    {
        _log.Error(e);
    }
    finally
    {
        _socket.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), _socket);
        //_socket.BeginReceiveFrom(_buffer, 0, _buffer.Length, SocketFlags.None, ref ep, new AsyncCallback(ReceiveCallback), _socket);
    }
}

我的单元测试程序

class Program
{
    static ConcurrentQueue<CallListLine> _workerQueue = new ConcurrentQueue();


    static void Main(string[] args)
    {
        Console.WriteLine("Create Configuration");
        ConfigurationHelper.Configuration.LoadOrCreateConfiguration();
        _workerQueue.AddProvider("Testsystem");

        MulticastConfiguration mc = new MulticastConfiguration
        {
            LocalIPAddress = "192.168.0.15",
            LocalPort = 0,
            RemoteIPAddress = "233.233.233.233",
            RemotePort = 43238,
            MaxSegmentSize = 200,
            ReceiveBufferSize = 8192,
            SocketBufferSize = 64000,
            IsConfigured = true
        };

        Console.WriteLine(mc);

        MulticastReceiver mr = new MulticastReceiver(mc);

        Console.WriteLine("Init");
        mr.Initialize();

        Console.WriteLine("Creating PDU Helper");

        mr.NewCallListReady += CallListReadyToProcess;

        mr.Receive();

        int counter = 0;
        while (true)
        {
            Console.WriteLine("Messages for Testsystem: {0}, Counter: {1}", _workerQueue.Count, counter);
            Thread.Sleep(1000);
            if (counter == 20)
                break;
            counter++;
        }

        Console.WriteLine("Press any Key to End!");
        Console.ReadLine();
        mr.Stop();
    }

    static void CallListReadyToProcess(object sender, EventArgs e)
    {
        MTPEventArgs test = e as MTPEventArgs;

        Console.WriteLine("Received new Line: {0}", test.CallList);

        CallListLine tempLine = new CallListLine
        {
            Provider = "Testsystem",
            Data = test.CallList,
            TimeStamp = DateTimeOffset.Now
        };
        _workerQueue.Enqueue(tempLine);
    }
}
c# sockets asynccallback beginreceive
1个回答
0
投票

我在这里的一个较旧的问题中找到了解决方案:https://stackoverflow.com/a/46086111/12798388

每次再次调用BeginReceiveFrom时,都需要删除并读取成员资格。

© www.soinside.com 2019 - 2024. All rights reserved.