C#Multicast UDP连接,BeginReceiveFrom异步调用停止被调用

时间:2013-12-19 13:18:36

标签: c# networking udp

这是我的第一篇文章,如果我做了我不应该做的事,请提前对不起。我总是在这里寻找答案,但这次我没有看到我的问题。我在C#中有一个项目,我保持连接UDP从数据流中侦听多播IP。

我正在监听的IP是一个多播流媒体,它从许多跟踪系统发送跟踪数据,因此我们可以假设发送方不是问题。它发送类似1024字节的数据包,60 fps。

这是从整个项目中提取的一个小例子,简化并且就我测试而言,其行为与大项目中的行为相同。问题是,如果我在localhost中连接,这永远不会中断,但如果我连接到远程IP,这将在4分钟内或多或少停止工作。

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);
        }
    } 
}

我调试了一段时间,我可以看到总是调用sock.BeginReceiveFrom,在某些时候停止,AsyncReceiveCallback永远不会再次执行。也许我在这里做的事情很愚蠢,但无论如何,我无法看到它。谢谢!

1 个答案:

答案 0 :(得分:0)

我遇到了完全相同的问题,这似乎只出现在WiFi接口上,而不是硬连线接口上。我发现的解决方案是在调用SocketOptionName.AddMembership之前始终设置BeginReceiveFrom()选项。

在接收回调中,在调用EndReceiveFrom()之后,为多播地址设置SocketOptionName.DropMembership选项。

然后再次致电BeginReceiveFrom()之前,请设置SocketOptionName.AddMembership选项。

不确定为什么必须为WiFi接口做这件事,但它对我有用。