考虑以下代码:

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


在上面的代码中,EndReceive和下一个BeginReceive之间没有人在听,所以我认为如果在这段时间内有一条消息,它将丢失。

好吧,我想这里有某种缓冲,但是即使缓冲在没有人监听消息的时间段内填满,消息也会丢失。

我记得有人说过,可以通过多次在同一端点上调用BeginReceive来解决此问题,因此我尝试了以下操作:

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


奇怪的是,在同一套接字上调用begin receive不会引发错误,但是每次接收到一条消息时,所有五个beginReceive都会触发并且所有五个消息都相同。

有什么办法可以改善代码?

最佳答案

首先,不能保证在使用UDP时将获取所有数据,因此无论如何都必须使代码/协议具有容错能力。

除非您的处理非常密集,并且您期望大量数据涌入,否则您可能无需采取其他措施。只需添加一些错误检测代码,这样您就可以知道代码是否无法应对。

但是,如果需要保持快速的接收循环,则在接收数据时,请将其复制到队列中以供其他线程处理,以便您可以快速开始重新读取。或者在某些情况下,您可能可以编写您的最终接收器,以便在多个数据包背对背输入时,它可以处理重入。

09-06 09:55