具有多个用户的 C# UDP 服务器

标签 c# udp

考虑代码:

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 之间有一个没有人在监听的时间跨度,我认为如果在这个时间跨度内有消息,它将丢失。 p>

好吧,我猜是有某种缓冲区,但即便如此,如果缓冲区在没有人监听消息的时间跨度内填满,消息也会丢失。

我记得有人说这可以通过在同一端点多次调用 BeginReceive 来非常简单地解决,所以我尝试了这个:

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

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

有什么办法可以改进代码吗?

最佳答案

首先,无法保证您在使用 UDP 时会获得所有数据,因此无论如何您都必须使您的代码/协议(protocol)容错。

除非您的处理非常密集,并且您预计会有大量数据涌入,否则您可能不需要采取不同的做法。只需添加一些错误检测代码,这样您就会知道您的代码是否无法应对。

但是,如果您需要保持接收循环快速,当您接收到数据时,将其复制到队列中以供另一个线程处理,以便您可以快速再次开始读取。或者在某些情况下,您可以编写最终接收,以便在多个数据包背靠背传入时它可以处理重新进入。

关于具有多个用户的 C# UDP 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10538862/

相关文章:

c++ - UDP 发送()到 Winsock 下的本地主机丢弃数据包?

c# - 如何在 emgucv c# 上实现非锐化 mask

c# - TcpClient 的 NetworkStream 什么时候完成一次读操作?

udp - 未兑现 receiveBufferSize。 UDP 数据包被截断

c++ - UDP客户端-服务器程序使用gcc编译,而不是g++

数据报 (UDP)winsocket 的 C++ 问题通过环回适配器在同一套接字上发送和接收

c# - Linux 上的 TCP 代理错误

c# - 为什么我会收到消息 "Invalid setup on a non-virtual (overridable in VB) member..."的异常?

c# - 名为 'System' 的表的 LINQ to SQL 问题

c++ - 绑定(bind)并连接的 Boost.Asio 数据报 (UDP) 套接字