2011-05-03 17 views
4

RCON協議實現令人難以置信的問題,我再次需要你的幫助搞清楚我這個問題......已經一天我似乎無法找出爲什麼,這是在我的代碼和輸出發生。心靈關於C#

好了.....所以基本上我想實現閥門的RCON Protocol在C#中,至今我收到expected output給出下面的代碼和樣本用法:

用法:

RconExec(socket, "cvarlist"); 

代碼:

private string RconExec(Socket sock, string command) 
{ 
    if (!sock.Connected) throw new Exception("Not connected"); 

    //sock.DontFragment = true; 
    sock.ReceiveTimeout = 10000; 
    sock.SendTimeout = 10000; 
    //sock.Blocking = true; 

    Debug.WriteLine("Executing RCON Command: " + command); 

    byte[] rconCmdPacket = GetRconCmdPacket(command); 
    sock.Send(rconCmdPacket); //Send the request packet 
    sock.Send(GetRconCmdPacket("echo END")); //This is the last response to be received from the server to indicate the end of receiving process 
    RconPacket rconCmdResponsePacket = null; 

    string data = null; 

    StringBuilder cmdResponse = new StringBuilder(); 

    RconPacket packet = null; 
    int totalBytesRead = 0; 

    do 
    { 
     byte[] buffer = new byte[4]; //Allocate buffer for the packet size field 
     int bytesReceived = sock.Receive(buffer); //Read the first 4 bytes to determine the packet size 
     int packetSize = BitConverter.ToInt32(buffer, 0); //Get the packet size 

     //Now proceed with the rest of the data 
     byte[] responseBuffer = new byte[packetSize]; 

     //Receive more data from server 
     int bytesRead = sock.Receive(responseBuffer); 

     //Parse the packet by wrapping under RconPacket class 
     packet = new RconPacket(responseBuffer); 
     totalBytesRead += packet.String1.Length; 

     string response = packet.String1; 
     cmdResponse.Append(packet.String1); 

     Debug.WriteLine(response); 

     Thread.Sleep(50); 

    } while (!packet.String1.Substring(0,3).Equals("END")); 

    Debug.WriteLine("DONE..Exited the Loop"); 
    Debug.WriteLine("Bytes Read: " + totalBytesRead + ", Buffer Length: " + cmdResponse.Length); 

    sock.Disconnect(true); 

    return ""; 
} 

問題:

這還不是最終的代碼,因爲我只是在調試窗口中測試輸出。如果我將代碼修改爲實際狀態,會出現一些問題。

  1. 刪除Thread.Sleep(50)

    • 如果我刪除Thread.Sleep(50),輸出未完成並最終拋出異常。我注意到'END'終止字符串是由服務器提前發送的。只有當整個列表完成時,這個字符串纔會被服務器發送。 Exception Thrown我測試了無數次同樣的事情發生,如果我不刪除行,列表完成並正常運行退出循環。
  2. 卸下環內Debug.WriteLine(response);並輸出使用Debug.WriteLine(cmdResponse.ToString());外循環的串,則僅顯示部分列表數據。如果我將從循環中讀取的實際字節與StringBuilder實例的長度進行比較,它們是一樣的嗎?點擊here生成輸出。

爲什麼在上述兩種情況下發生這種情況?

回答

3

你是不是考慮Socket.Receive非常好可能比提供的緩衝區的長度讀取的字節數更少。返回值告訴你實際讀取的字節數。我看到你正在將這個值存儲在一個變量中,但我看不到任何使用它的代碼。

你應該準備好多次調用Receive檢索整個包。特別是當您收到包裹數據時。

我不知道這是你的問題的原因。但是,它可能是,因爲在客戶端在短暫的延遲可能足以使整個封裝在單個調用讀填補了網絡緩衝區。

嘗試使用下面的代碼來檢索包數據:

int bufferPos = 0; 
while (bufferPos < responseBuffer.Length) 
{ 
    bufferPos += socket.Receive(responseBuffer, bufferPos, responseBuffer.Length - bufferPos, SocketFlags.None); 
} 

注意:您也應該支持的情況下,以Receive第一個呼叫(您收到數據包的數據長度的)不返回4字節。

+0

感謝您的建議!我誤以爲無論我在接收方法中放入的大小是服務器通過一次調用發送的預期字節數量。我甚至沒有檢查收到的字節數量!當我回家時,我會試試這個。再次感謝! – 2011-05-03 23:59:48

+0

更新:解決問題:)非常感謝!我會牢記這一點。 – 2011-05-04 08:58:47