Jesse Jesse - 8 days ago 5
C# Question

Testing UDP Locally C#

I am writing a mono C# application that needs to use UDP. I was writing my test suite so that I could make sure packets are received properly with NUnit.

I made a minimal working example with a

UdpCom
class that is supposed to just listen right now and print out the bytes it receives in the call back method.

My minimal
UdpCom
class looks like:

using System;
using System.Net;
using System.Net.Sockets;


namespace UdpPractice
{
public class UdpState
{
public UdpClient client;
public IPEndPoint endpoint;
public UdpState(UdpClient c, IPEndPoint iep)
{
this.client = c;
this.endpoint = iep;
}
}
public class UdpCom
{
public UdpState uState;
public UdpClient uClient;
public IPAddress address;
public int port;
public IPEndPoint uEndpoint;

public UdpCom (IPAddress address, int port)
{
uEndpoint = new IPEndPoint (address, port);
uClient = new UdpClient (uEndpoint);
uState = new UdpState (uClient, uEndpoint);
uClient.BeginReceive (new AsyncCallback(RxCallback), uState);
}

public void RxCallback(IAsyncResult result)
{
UdpState rState = (UdpState)(result.AsyncState);
UdpClient rClient = rState.client;
IPEndPoint rEndPoint = rState.endpoint;
byte[] rxBytes = rClient.EndReceive (result, ref rEndPoint);
Console.WriteLine ("Received Bytes ___________________________");
Console.WriteLine (rxBytes.ToString ());

rClient.BeginReceive (new AsyncCallback(RxCallback), rState);
}
}
}


My simple test instantiates this class and then sends it a dummy packet of bytes. I am not testing the result right now, just placing a break point in my
RxCallback
method.

This is my NUNIT test:

using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UdpPractice;

namespace UdpTest
{
[TestFixture ()]
public class Test
{
[Test ()]
public void TestCase ()
{
// Setup Receiver
IPAddress address = new IPAddress (new byte[] { 127, 0, 0, 1 });
int port = 14580;
UdpCom com = new UdpCom (address, port);
com.uClient.Connect (com.uEndpoint);
// Set up sender
UdpClient sender = new UdpClient(new IPEndPoint (address, port));
sender.Connect (address, port);

// Dummy Data
byte [] dummyData = new byte[] {1, 2, 3, 4, 4, 5};

sender.Send (dummyData, dummyData.Length);
Thread.Sleep (100);

// Close
sender.Close ();
com.uClient.Close ();
}
}
}


My Issue is that when I'm in the
RxCallback
method on the line that I'm trying to retrieve the bytes I am getting this exception:

System.ObjectDisposedException has been thrown
Cannot access a disposed object.
Object name: System.Net.Sockets.UdpClient


I want to be able to store these bytes in a queue in my
UdpCom
class but I am having trouble accessing them in the first place.

I may be failing to udner stand some basic UDP concepts as well here but it seems pretty straght forward.

The udp examples I have been following are:



EDIT
I updated my class and tests as follows so I don't use the local loopback. But I am still getting the same exception.
UdpCom
is now:

using System;
using System.Net;
using System.Net.Sockets;


namespace UdpPractice
{
public class UdpState
{
public UdpClient client;
public IPEndPoint endpoint;
public UdpState(UdpClient c, IPEndPoint iep)
{
this.client = c;
this.endpoint = iep;
}
}
public class UdpCom
{
public UdpState uState;
public UdpClient uClient;
public IPAddress address;
public int port;
public IPEndPoint uEndpoint;

public UdpCom (IPAddress address, int port)
{
uEndpoint = new IPEndPoint (address, port);
uClient = new UdpClient (uEndpoint);
uState = new UdpState (uClient, uEndpoint);
uClient.BeginReceive (new AsyncCallback(RxCallback), uState);
}

public void RxCallback(IAsyncResult result)
{
UdpState rState = (UdpState)(result.AsyncState);
UdpClient rClient = rState.client;
IPEndPoint rEndPoint = rState.endpoint;
byte[] rxBytes = rClient.EndReceive (result, ref rEndPoint);
Console.WriteLine ("Received Bytes ___________________________");
Console.WriteLine (rxBytes.ToString ());

rClient.BeginReceive (new AsyncCallback(RxCallback), rState);
}
}
}


and the test is:

using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UdpPractice;

namespace UdpTest
{
[TestFixture ()]
public class Test
{
[Test ()]
public void TestCase ()
{
// Setup Receiver
IPAddress address = new IPAddress (new byte[] { 192, 168, 1, 161 });
int port = 14580;
UdpCom com = new UdpCom (IPAddress.Any, port);
// com.uClient.Connect (com.uEndpoint);
// Set up sender
UdpClient sender = new UdpClient(new IPEndPoint (address, port));
sender.Connect (address, port);

// Dummy Data
byte [] dummyData = new byte[] {1, 2, 3, 4, 4, 5};

sender.Send (dummyData, dummyData.Length);
Thread.Sleep (100);

// Close
sender.Close ();
com.uClient.Close ();
}
}
}

Answer

I guess I was struggling with a basic misunderstanding with how to communicate with UDP.

UdpCom:

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;

namespace UdpPractice
{
    public class UdpState
    {
        public UdpClient client;
        public IPEndPoint endpoint;
        public UdpState(UdpClient c, IPEndPoint iep)
        {
            this.client = c;
            this.endpoint = iep;
        }
    }
    public class UdpCom
    {
        public UdpState uState;
        public IPAddress address;
        public int port;
        public IPEndPoint uEndpoint;
        public bool receiveFlag;
        public List<byte[]> rxBytesBuffer;

        public UdpCom (IPAddress address, int port)
        {
            uEndpoint = new IPEndPoint (address, port);
            // uClient = new UdpClient (uEndpoint);
            uState = new UdpState (new UdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), port)), uEndpoint);
            receiveFlag = false;
            uState.client.BeginReceive (new AsyncCallback(RxCallback), uState);
            rxBytesBuffer = new List<byte[]> ();
        }

        public void RxCallback(IAsyncResult result)
        {
            UdpState rState = (UdpState)result.AsyncState;
            UdpClient rClient = ((UdpState)result.AsyncState).client;
            IPEndPoint rEndPoint = ((UdpState)result.AsyncState).endpoint;
            byte[] rxBytes = rClient.EndReceive (result, ref rEndPoint);
            rxBytesBuffer.Add (rxBytes);
            Console.WriteLine ("Received Bytes ___________________________");
            Console.WriteLine (rxBytes.ToString ());
            receiveFlag = true;
            rClient.BeginReceive (new AsyncCallback(RxCallback), result.AsyncState);
        }
    }
}

Test:

using NUnit.Framework;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UdpPractice;

namespace UdpTest
{
    [TestFixture ()]
    public class Test
    {
        [Test ()]
        public void TestCase ()
        {
            // Setup Listener
            int port = 14580;
            IPEndPoint locep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
            // Server (Listener)
            UdpCom com = new UdpCom (IPAddress.Any, port);
            // Set up sender
            UdpClient sender = new UdpClient();
            // Dummy Data
            byte [] dummyData = new byte[] {1, 2, 3, 4, 4, 5};
            sender.Send (dummyData, dummyData.Length, locep);
            sender.Send (dummyData, dummyData.Length, locep);
            Thread.Sleep (100);
            Assert.AreEqual(true, com.receiveFlag);
        }
    }
}

I needed to make the listener listen to IPAddress.Any and then I mainly used the Send method with the EndPoint argument. I had to add the delay in there because otherwise the receive flag wasn't being set.