Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# UDP Server with multiple users

Tags:

c#

udp

Consider the code:

class UPDServer {

    //start listener
    public void start() {
        UdpClient listener = new UdpClient(this._porta);
        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 10000);

        State s = new State();
        s.listener = listener;
        s.ipEndPoint = ipEndPoint;

        // begin to listen again
        listener.BeginReceive(new AsyncCallback(ReceiveCallback), s);

   }

 //receive data
   public void ReceiveCallback(IAsyncResult ar)
   {
      // we got data
      State s = (State)(ar.AsyncState);

      Byte[] received = e.escuta.EndReceive(ar, ref e.ipEndPoint);
      string text = ""; = Encoding.ASCII.GetString(received);
      // ... do somenthing with text

      // begin to listen again
      s.listener.BeginReceive(new AsyncCallback(ReceiveCallback), e);
   }
}

On the code above there is a time span between the EndReceive and the next BeginReceive that no one is listening, i think if there is a message in this time span it will be lost.

Well, i guess there isw some kind o buffer, but even so if the buffer fill up in the time span where no one is listening for messages, messages will be lost.

I remember someone saying that this could be solved very simple by calling BeginReceive on the same end point several times, so i tried this:

   for( int x = 0; x < 5;x++) {
      escuta.BeginReceive(new AsyncCallback(ReceiveCallback), e);
   }

Oddly calling begin receive on the same socket does no throw errors but every time a message is received all five beginReceive fires and all five got the same message.

Is there any way to improve the code?

like image 700
uacaman Avatar asked Nov 05 '22 00:11

uacaman


1 Answers

Firstly, there is no guarantee that you will get all your data when using UDP, so you have to make your code/protocol fault tolerant regardless.

Unless your processing is very intensive and you're expecting huge amounts of data to flood in you probably don't need to do things differently. Just add some error detection code so you will know if your code is failing to cope.

However, if you need to keep your receive loop fast, when you receive the data, copy it onto a queue for another thread to process so that you can begin reading again quickly. Or under some circumstances you may be able to write your end-receive so it can handle going re-entrant if several packets come in back to back.

like image 129
Jason Williams Avatar answered Nov 12 '22 11:11

Jason Williams