C# Multicast UDP connection, BeginReceiveFrom async call stops to be called

[亡魂溺海] 提交于 2021-01-27 20:25:15

问题


this is my first post, sorry in advance if I do something I shouldn't. I always search here for answer but this time I saw nothing about my problem. I have a project in C# where I keep alive a connection UDP listening a multicast IP from a data streaming.

The IP I'm listening is a multicast streamer that sends tracking data from many tracking systems, so we can assume the sender is not the problem. It sends like 1024 bytes packets, 60 fps.

This is a small example extracted from the whole project, simplified and as far as I tested, behaves in the same way as in the big project. The problem is that if I connect in localhost this never break, but if I connect to remote IPs this stop working, more or less, in 4 minutes.

public class TrackingStateObject
{
    public Socket workSocket = null;
    public const int BUFFER_SIZE = 65507;
    public byte[] buffer = new byte[BUFFER_SIZE];
}

class MainClass
{
    static public string multicastServerIPAddress = "239.255.42.99";
    static public string realTrackingServerIPAddress = "161.116.27.144";
    static protected EndPoint trackingEndPoint;

    static public int dataPort = 2345;
    static protected Socket sockData = null;

    static int foo = 0;

    public static void Main (string[] args)
    {
        IPEndPoint ipep;
        TrackingStateObject so;

        IPAddress trackingIP = IPAddress.Parse(multicastServerIPAddress);
        trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
        sockData = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

        ipep = new IPEndPoint(IPAddress.Any, dataPort);

        try {
            sockData.Bind(ipep);
        }
        catch (Exception ex) {
            System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
            return;
        }

        sockData.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(trackingIP));
        try {
            trackingIP = IPAddress.Parse(realTrackingServerIPAddress);
            trackingEndPoint = new IPEndPoint(trackingIP, dataPort);
        }
        catch(Exception ex) {
            System.Console.WriteLine("[UDPClient] Exception "+ex.Message);
            return;
        }

        so = new TrackingStateObject();
        so.workSocket = sockData;
        sockData.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, 0, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);

        System.Threading.Thread.Sleep (600000);
    }

    private static void AsyncReceiveCallback(IAsyncResult ar)
    {
        try {
            TrackingStateObject so = (TrackingStateObject)ar.AsyncState;
            Socket sock = so.workSocket;
            int read = sock.EndReceiveFrom(ar, ref trackingEndPoint);
            if (read > 0)
            {
                // Do things with the data
                System.Console.WriteLine("Recieved shit, " + read + " bytes, " + foo++ + " times.");
            }

            sock.BeginReceiveFrom(so.buffer, 0, TrackingStateObject.BUFFER_SIZE, SocketFlags.None, ref trackingEndPoint, new AsyncCallback(AsyncReceiveCallback), so);
        }
        catch (Exception e) {
            System.Console.WriteLine("[UDPClient] Exception AsynCallback "+e.Message);
        }
    } 
}

I debugged for a while and as far I can see is that always sock.BeginReceiveFrom is called, stop in some point, AsyncReceiveCallback is never executed again. Perhaps I'm doing here something stupid, but in any case, I'm not able to see it. Thanks!


回答1:


I was having exactly the same problem, which only seems to occur on WiFi interfaces, not hardwired interfaces. The solution I discovered was to always set the SocketOptionName.AddMembership option before calling BeginReceiveFrom().

In the receive callback, after calling EndReceiveFrom() then set the SocketOptionName.DropMembership option for the multicast address.

Then before calling BeginReceiveFrom() again, set the SocketOptionName.AddMembership option.

Not sure why this has to be done for WiFi interfaces, but it worked for me.



来源:https://stackoverflow.com/questions/20682830/c-sharp-multicast-udp-connection-beginreceivefrom-async-call-stops-to-be-called

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!