2012-08-22 23 views
4

正如標題所示,我在C#中遇到了UDP問題。 我正在嘗試爲遊戲DayZ的rcon協議建立一個庫。儘管所有數據包都到達C#UDP packetloss(WireShark)

我的問題是,我沒有收到我應得到的每個數據包。 發送一個命令後,服務器回覆一個拆分答案。數據包標題包含總數據包數量和當前數據包的索引。 現在,如果我應該得到17個數據包,我只能得到8-15個數據包。

使用WireShark進行測試後,我現在知道所有包都到達了我的電腦。他們只是沒有得到我的應用程序或類似的東西的認可。

我的實際問題是: 是否可以防止丟失我的網卡和我的應用程序之間的軟件包?或 爲什麼會發生?

這是我目前的代碼。它非常髒,因爲我無法按預期工作後,撕開它拆開:

private Socket _udpClient; 
    private Thread _receiverThread; 
    private Thread _workerThread; 
    private Queue<byte[]> _packetQueue; 
    private PacketBuffer[] MessageBuffer; 
    private byte SenderSequence = 0; 
    private IPEndPoint connection; 

    public RCon(IPAddress ip, int port) 
    { 
     connection = new IPEndPoint(ip, port); 
     _udpClient = new Socket(connection.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp); 
     _udpClient.Connect(connection); 
     MessageBuffer = new PacketBuffer[256]; 
     _packetQueue = new Queue<byte[]>(); 

     _receiverThread = new Thread(new ThreadStart(ReceiveCallback)); 
     _receiverThread.IsBackground = true; 
     _receiverThread.Priority = ThreadPriority.AboveNormal; 
     _receiverThread.Start(); 
     _workerThread = new Thread(new ThreadStart(WorkerCallback)); 
     _workerThread.IsBackground = true; 
     _workerThread.Start(); 
    } 

    public void Login(string password) 
    { 
     LoginPacket packet = new LoginPacket(password); 

     _udpClient.Send(packet.Bytes); 
    } 

    public void SendCommand(string command) 
    { 
     CommandPacket packet = new CommandPacket(SenderSequence, command); 
     SenderSequence++; 

     _udpClient.Send(packet.Bytes); 
    } 

    private void ReceiveCallback() 
    { 

     while (true) 
     { 
       byte[] buffer = new byte[1036]; 
       if (_udpClient.Receive(buffer) > 0) 
        _packetQueue.Enqueue(buffer); 
     } 
    } 

    private void WorkerCallback() 
    { 
     while (true) 
     { 
      if (_packetQueue.Count > 0) 
      { 
       byte[] buffer = _packetQueue.Dequeue(); 

       if (buffer != null) 
       { 
        try 
        { 
         Packet receivedPacket = Packet.ParseIncoming(buffer); 

         OnPacketReceived(new PacketReceivedEventArgs(receivedPacket)); 

         switch (receivedPacket.Type) 
         { 
          case PacketType.Message: 
           OnMessageReceived(new MessageReceivedEventArgs(receivedPacket.Content)); 
           MessageCallbackPacket packet = new MessageCallbackPacket(receivedPacket.SequenceNumber); 
           _udpClient.Send(packet.Bytes); 
           break; 
          case PacketType.CommandCallback: 
           if (MessageBuffer[receivedPacket.SequenceNumber] == null) 
            MessageBuffer[receivedPacket.SequenceNumber] = new PacketBuffer(receivedPacket); 
           else 
            MessageBuffer[receivedPacket.SequenceNumber].AddPacket(receivedPacket); 

           if (MessageBuffer[receivedPacket.SequenceNumber].IsComplete) 
            OnCommandCallback(new CommandCallbackEventArgs(MessageBuffer[receivedPacket.SequenceNumber].GetContent())); 
           break; 
         } 
        } 
        catch (ArgumentException) { } 
        catch (OverflowException) { } 
        catch (FormatException) { } 
       } 
      } 
     } 
    } 
+1

我總是驚訝於有多少聰明人不知道「鬆散」與「輸」不是同一個詞。 –

+1

謝謝你幫助我增加我的英語知識。 – Swarley

+0

'_udpClient.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReceiveBuffer,一個很大的值,如0x40000);' –

回答

4

這通常是因爲你不消耗你的數據報速度不夠快,所以在內核套接字緩衝區得到充分和網絡堆棧開始下降新到數據包。幾點:

  • 增加插座上的接收緩衝區,
  • 不要在每個迭代上獲取鎖 - 多讀就可以了,然後把數據放入隊列,
  • 考慮無阻塞而不是線程。
+0

增加接收緩衝區爲我工作。對於非阻塞,你的意思是BeginReceive&EndReceive對嗎?我之前使用過,但切換到線程進行測試。感謝您的幫助! – Swarley

+0

不,我的意思是非阻塞套接字,並取消線程。 .NET異步回調在線程池中運行。 –