2

好的,这是我的第一个堆栈溢出问题,所以请随时提出更好的提问方式或下次我应该包括的内容。大多数时候我可以谷歌得到我的答案,但这一个有点棘手......

我正在用 C# 编写一个 Windows 应用程序,它侦听 UDP 端口,然后处理传入的 UDP 消息。更具体地说,我正在使用UDPClient该类并使用 BeginReceive 方法进行侦听。接收回调依次触发它自己的消息接收事件,然后再次重置 UDP 客户端。此“MessageReceived”事件随后由处理器对象处理。

我认为这一切都很聪明,直到我的经理向我提出了一些问题,例如:

  • 一次可以接收多少条消息?如果我们得到更多,会发生什么?
  • 如果处理时间过长,消息是排队还是会丢失?
  • 如果处理时间过长会发生什么?

我们不能丢失消息,因为最后一个消息仍在处理中,并且我们不能在系统崩溃之前进行构建,因为它也内存不足。他想听到(而且理所当然地)是某种验证,即有一种确定性的方式来处理消息的“风暴”。不幸的是,我不知道去哪里得到答案。我已经包含了我认为是下面的相关代码。

所以:

  1. 有人知道以上问题的答案吗?
  2. 我会在哪里做一些研究来找到这些答案和/或这种事情要遵循的一些模式?
  3. 我可以使用什么样的工具来观察调试/性能分析的处理过程?
  4. 如果我在设计中犯了一个巨大的错误,我应该怎么做才能解决它(即引入队列、使用线程池等)?

    public void ReceiveCallback(IAsyncResult ar)
    {
        //Cast the item back to the listener
        UdpListener listener = (UdpListener)ar.AsyncState;
    
        //If we are supposed to be listening, then get the data from the socket
        //Listen is false during shutdown
        if (Listen)
        {
            //The try catch is placed inside the listen loop so that if there is an error in the processing it will 
            //recover and listen again. this may cause more exceptions but we can be sure that it will not
            // stop listening without us knowing
            try
            {
                //Address and port from the external system
                IPEndPoint ep = listener.EndPoint;
    
                //Get the data from the async read
                Byte[] receiveBytes = listener.Client.EndReceive(ar, ref ep);
    
                //Reset the socket to listen again
                listener.Client.BeginReceive(new AsyncCallback(ReceiveCallback), listener);
    
                //Execute the event to pass external components the message
                HeartbeatEventArgs hea = new HeartbeatEventArgs(DateTime.Now, ep, receiveBytes);
                OnHeartbeatReceived(hea);
    
                //Ack back to the external system
                HeartbeatAcknowledgement(new IPEndPoint(ep.Address, ep.Port), receiveBytes);
            }
            catch (Exception e)
            {
                log.Error(e.Message);
                //Reset the socket to listen again
    
            }
        }
    }
    

listner 只是UDPClient. 如下:

#region UdpClient Wrapper (UdpListener)
/// <summary>
/// UdpListener is used to control the asynchronous processing of a UDPClient object. 
/// </summary>
public class UdpListener
{
    /// <summary>
    /// IPEndpoint on which to accept a connection. Usually set to "Any".
    /// </summary>
    public IPEndPoint EndPoint { get; set; }
    /// <summary>
    /// The socket based client object that is used for communication
    /// </summary>
    public UdpClient Client { get; set; }

    public UdpListener(int port)
    {
        EndPoint = new IPEndPoint(IPAddress.Any, port);
        Client = new UdpClient(EndPoint);
    }
}
#endregion

谢谢,

丁斯代尔

4

1 回答 1

1

如果丢失消息是一个问题,那么 UDP 不适合您。UDP 只保证如果消息到达,它将是完整的。它不保证消息的顺序或交付。换句话说,如果客户端发送两条消息,您可能会乱序接收它们,或者只接收第一条消息,或者只接收最后一条消息(或根本没有)。如果您需要保证交付和订单,请改用 TCP(TCP 带有它自己的一组保证和陷阱)。

关于它可以处理多少条消息,您将有一个上限。如果您处理消息的速度不快于它们到达的速度,那么它们将在您的应用程序层或 UDP 网络层中排队。一旦网络缓冲区已满,您的网络接口就会开始丢弃消息。

于 2013-02-18T23:26:18.343 回答