gcb
gcb

Reputation: 376

UDP sometimes can't receive anything

I have a C# application that receives UDP data from a remote host. I find that sometimes my socket receives nothing and I cant seem to find any clues as to why! Wireshark tells me my data is being sent from the remote device correctly. I cant seem to get why sometimes I can receive fine, and sometimes I can't.

I don't get any exceptions, but OnRecieve never gets called

Here is my code in case it helps:

class cUdpRx
{
    private Thread rxThread = null;
    private Socket UdpSocket;
    private IPEndPoint localEp;
    byte[] byData;
    //rxbytes event
    public delegate void OnRxBytesEventHandler(byte[] rxBuf);
    public event OnRxBytesEventHandler OnRxBytesEvent;



    /// <summary>
    /// Creates the udp socket
    /// </summary>
    /// <param name="Port"></param>
    /// <returns></returns>
    public bool CreateSocket(int Port)
    {
        try
        {
            byData = new byte[1500]; //create our buffer
            UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            localEp = new IPEndPoint(IPAddress.Any,Port);
            UdpSocket.Bind(localEp);
            UdpSocket.BeginReceive(byData,0,byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket);

            return true;    //seemed to work ok
        }
        catch
        {
            Dispose();
            return false;   //something went wrong, abort
        }
    }

    private void OnRecieve(IAsyncResult iar)
    {
        byte[] rxData;
        int nBytesRec = 0;
        Socket socket = (Socket)iar.AsyncState;
        try //in case something else has already disposed of the socket
        {
            nBytesRec = socket.EndReceive(iar);
        }
        catch
        {
            Debug.WriteLine("cant access udp rx socket");
        }
        try
        {
            if (nBytesRec > 0)
            {
                rxData = new byte[nBytesRec];
                Array.Copy(byData, rxData, nBytesRec); //copy exact data into new array
                OnRxBytesEvent(rxData);
            }
            if(!killThreads)
                UdpSocket.BeginReceive(byData, 0, byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket);
        }
        catch(SocketException se)
        {
            Debug.WriteLine(se.ToString());
        }
    }

Any help would be really appreciated as its stopping me from going forward with my project. Thanks

UPDATE It seems like using IPAdress.any is the problem. If I change:

localEp = new IPEndPoint(IPAddress.Any,Port);

to

localEp = new IPEndPoint(IPAddress.Parse("192.168.0.33"),Port);

where 192.168.0.33 is the IP address of my computer, it receives data every time. Can anyone explain why? It is quite useful to use IPAddress.any and receive from both wireless and wired connections. IPAddress.any is equivalent to 0.0.0.0 and according to MSDN it should receive on all network interfaces.

Upvotes: 4

Views: 4391

Answers (2)

Foxy
Foxy

Reputation: 1

I just got the same problem and resolve it by set timeTolive to big data.

_client = new UdpClient();
_client.Client.Bind(new IPEndPoint(IPAddress.Any, targetURI.Port));
_client.JoinMulticastGroup(IPAddress.Parse(targetURI.Host) , 250);
  • timeToLive = 250, it works.
  • timeToLive = 50 , works or not work alternate happened.
  • timeToLive = none or 0, not work.

Upvotes: 0

Nikolai Fetissov
Nikolai Fetissov

Reputation: 84239

The usual cause of such problems is not processing packets fast enough. They fill up socket receive buffer and kernel starts dropping them.

Increase socket receive buffer size to accommodate traffic bursts. Remove everything non-essential from the fast socket reading path. Consider simple iterative approach bellow instead of working against thread pool:

rxData = new byte[nBytesRec];

while ( !time_to_stop ) {
    int len = socket.Receive( rxData );
    OnRxBytesEvent( rxData, len );
}

Your code comments mention multicast. Note that you need to add explicit group membership for that, and the fact that you join a multicast group on an interface (either explicitly or as decided via routing table), so if you want to listen for multicast data on two interfaces you need two sockets.

Upvotes: 1

Related Questions