【问题标题】:Why do I received UDP socket answer randomly with Asynchronous UDP client socket?为什么我使用异步 UDP 客户端套接字随机收到 UDP 套接字应答?
【发布时间】:2013-08-25 19:09:45
【问题描述】:

我有一个代码将 XML 文件发送到 UdpSocket 并收到答案。我发送和接收异步答案。我的问题是,当我收到来自 UDP 套接字的答案时,我无法将其保存到正确的文件中。我尝试了很多东西,但没有任何效果。

简短地解释我的代码。我开始在 Main() 方法中创建 3 AsynchronousConnection。从那里调用 static void AsynchronousConnection(object objectFilename) 我调用 UdpStartClient 方法。

从 UdpStartClient 方法中,我使用 UdpSendXmlFile(fileToSend, udpClient, bytes, CallDuration, out threadId); 发送一个文件

之后,我使用方法 UdpReceivedXmlFile("c:\Received" + filename, udpClient, remoteEPReceived, CallDuration, out threadId); 在 while 循环中收到了答案。

我在 UdpReceivedXmlFile 方法中收到的答案将保存到文件中。我想,我的问题就在这里。我通过 AsynchronousConnection 发送 3 个文件并从 UDP 套接字接收到 3 个答案,但答案与我发送的文件不匹配。

例如,我发送这 3 个文件。

MessagingText4000.xml

MessagingText4001.xml

MessagingText8.xml

我随机收到答案,例如:

文件MessagingText4000.xml可以从MessagingText8.xml得到答案

文件MessagingText4001.xml可以从MessagingText4000.xml得到答案

文件MessagingText8.xml可以从MessagingText4001.xml得到答案

你能帮我,所以我收到了正确文件的正确答案吗?

public delegate void AsyncMethodCall(object objectFilename, int callDuration, out int threadId, out string receivedXmlDataFromTNX);

// Program
public static void Main(String[] args)
{
  Thread newThread;
  newThread = new Thread(AsynchronousConnection);
  newThread.Name = "4001";
  newThread.Start("MessagingText4001.xml");

  newThread = new Thread(AsynchronousConnection);
  newThread.Name = "4000";
  newThread.Start("MessagingText4000.xml");

  newThread = new Thread(AsynchronousConnection);
  newThread.Name = "8";
  newThread.Start("MessagingText8.xml");
}


// Asynchronous Connection 
static void AsynchronousConnection(object objectFilename)
{
  int threadId; string receivedXmlData;
  UdpClass udpClass = new UdpClass();
  AsyncMethodCall caller = new AsyncMethodCall(udpClass.UdpStartClient);
  IAsyncResult result = caller.BeginInvoke(objectFilename, 500, out threadId, out receivedXmlData, null, null);
  result.AsyncWaitHandle.WaitOne();
  caller.EndInvoke(out threadId, out receivedXmlData, result);
  result.AsyncWaitHandle.Close();
}


// UdpClient received 
void UdpReceivedXmlFile(object objectFilename, UdpClient udpClient, IPEndPoint remoteEPReceived, int CallDuration, out int threadId)
{
  Thread.Sleep(CallDuration);
  threadId = Thread.CurrentThread.ManagedThreadId;
  try
  {
    // Blocks until a message returns on this socket from a remote host. 
    Byte[] receiveBytes = udpClient.Receive(ref remoteEPReceived);
    File.WriteAllText((string)objectFilename, Encoding.UTF8.GetString(receiveBytes));
  }
  catch (Exception ex)
  {
    Console.WriteLine("Contact webmaster with this error in UdpReceivedXmlFile:\n " + ex.ToString());
  }
}


// UdpClient send 
void UdpSendXmlFile(string fileToSend, UdpClient udpClient, byte[] bytes, int CallDuration, out int threadId)
{
  Thread.Sleep(CallDuration);
  threadId = Thread.CurrentThread.ManagedThreadId;
  try
  {
    // Encode the data string into a byte array 
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load(fileToSend);
    // Load XML fil
    string xmlContent = xmlDoc.OuterXml;
    byte[] msg = Encoding.UTF8.GetBytes(xmlDoc.OuterXml);
    // Send the data through the socket.
    udpClient.Send(msg, msg.Length);
  }
  catch (Exception ex)
  { Console.WriteLine("Contact webmaster with this error in UdpSendXmlFile:\n " + ex.ToString()); 
  }
}


// UdpStart Client
public void UdpStartClient(object objectFilename, int CallDuration, out int threadId, out string receivedXmlData)
{
  string filename = (string)objectFilename;
  receivedXmlData = null; Thread.Sleep(CallDuration);
  threadId = Thread.CurrentThread.ManagedThreadId;
  try
  {
    Console.WriteLine("1: UdpStartClient Async - id: " + threadId + " objectFilename: " + (string)objectFilename);
    fileToSend = fileLocation + filename;
    // Send a file to the UdpSocket 
    UdpSendXmlFile(fileToSend, udpClient, bytes, CallDuration, out threadId);

    TimeSpan maxTime = TimeSpan.FromSeconds(10);
    Stopwatch stopwatch = Stopwatch.StartNew();
    bool stopwatchStop = false;

    while (stopwatch.Elapsed < maxTime && !stopwatchStop)
    {
      // listed on UdpSocket and save to file 
      UdpReceivedXmlFileDirectToFile("c:\\Received" + filename, udpClient, remoteEPReceived, CallDuration, out threadId);
      attributXMLReceived = ReadXmlAttribut("c:\\Received" + filename, CallDuration, out threadId);

      if ((attributXMLReceived == "Status=Pending") || (attributXMLReceived == "Status=Sent"))
      {
        Console.WriteLine("Answer from XMl file:" + attributXMLReceived + " id: " + Thread.CurrentThread.ManagedThreadId + "\n");
      }
      else if (attributXMLReceived == "Status=Delivered")
      {
        Console.WriteLine("Answer from XMl file:" + attributXMLReceived + " id: " + Thread.CurrentThread.ManagedThreadId + "\n");
        stopwatchStop = true;
      }
      if (stopwatch.Elapsed == maxTime)
        Console.WriteLine("Timeout!");
    }
  }
  catch (Exception e)
  {
    Console.WriteLine(e.ToString());
  }
}

【问题讨论】:

    标签: c# asynchronous udpclient


    【解决方案1】:

    这就是 UDP 的工作原理。

    UDP 是一种在连接到 IP 网络的设备之间提供不可靠、无序数据传输的协议。它通常被认为是 OSI 堆栈中的“第 4 层”协议。 UDP 的一种流行用途是传输时间敏感信息,例如 IP 语音。 UDP 在 RFC 768 中指定。

    http://www.techabulary.com/u/udp/

    您要么需要使用 TCP,要么准备好处理无序(并且可能完全丢失)响应。

    SCTP 是您传输协议的另一种选择。

    【讨论】:

    • 理论上我同意你写的。但是在良好的网络中,或者在本地机器上工作时,我不希望 UDP 数据报以如此随机的顺序出现。难道这和他有3个可以按任何顺序运行的线程有关吗? TCP 会处理这个问题,但这不仅是因为它会对数据包进行排序,还因为每个线程都有单独的会话。
    • 我通过UDP接收到的数据包含一个ID号。当我在收到的数据字符串中有这个ID号时,我就知道收到的包属于哪个发送包。
    • 因此,我来​​跟踪 UDP 数据包的顺序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2012-07-17
    • 1970-01-01
    • 2011-08-15
    相关资源
    最近更新 更多