2011-04-12 67 views
0

我希望我沒有錯過一些愚蠢的東西。我正在開發一個應用程序,用於在多個手持窗口的移動計算機和中央服務器之間進行通信。目前的架構只允許短消息(最多4096字節),我正在修改應用程序以在必要時允許更大的通信。此代碼似乎間歇性地工作,具體取決於服務器的速度和網絡通信速度。我需要找到一種讓服務器的接收代碼更加穩固的方法。它偶爾可以很好地工作,其他時候手持拋出錯誤「無法將數據寫入傳輸連接,現有連接被遠程主機強制關閉」。在C中使用套接字進行通信的問題#

手持式發射代碼:

public bool SendMessage(NetworkStream ansStream, string asMessage) 
{ 
    try 
    { 
     Byte[] wBytes = System.Text.Encoding.ASCII.GetBytes(asMessage.ToCharArray()); 
     ansStream.Write(wBytes, 0, wBytes.Length); 
     return true; 
    } 
    catch (Exception E) 
    { 
     MessageBox.Show(E.Message, "Network Error"); 
     return false; 
    } 
} 

服務器端接收代碼:

public const int BUFFER_LENGTH = 4096; 
public void ProcessMessage(object aClient) 
{ 
    TcpClient wClient = (aClient as TcpClient); 
    try 
    { 
     byte[] wBytes = new byte[BUFFER_LENGTH]; 
     StringBuilder wMessage = new StringBuilder(); 
     using (NetworkStream wNetStream = wClient.GetStream()) 
     { 
      try 
      { 
       int wiRead = 0; 
       int wiTotalBytes = 0; 
       do 
       { 
        wiRead = wNetStream.Read(wBytes, 0, wBytes.Length); 
        wMessage.AppendFormat("{0}", Encoding.ASCII.GetString(wBytes, 0, wiRead)); 
        wiTotalBytes += wiRead; 

        // my attempt to ensure entire message is read 
        if (wNetStream.DataAvailable) 
        { 
         Thread.Sleep(1000); 
        } 

       } while (wNetStream.DataAvailable); 

       if (wiTotalBytes > 0) 
       { 
        string wsAnswerFile = ""; 
        string wsResult = DoBusinessProcess(wMessage.ToString(), out wsAnswerFile); 
        if (string.IsNullOrEmpty(wsAnswerFile)) 
        { 
         wBytes = Encoding.ASCII.GetBytes(wsResult); 
         wNetStream.Write(wBytes, 0, wBytes.Length); 
        } 
        else 
        { 
         if (File.Exists(wsAnswerFile)) 
         { 
          SendFile(wsAnswerFile, wNetStream); 
         } 
        } 
       } 
      } 
      catch (Exception E) 
      { 
       MessageBox.Show(E.Message, "Network Error"); 
      } 
      finally 
      { 
       if (wNetStream != null) 
       { 
        wNetStream.Close(); 
       } 
      } 
     } 
    } 
} 
+0

網絡錯誤很常見,您必須通過代碼才能存活它們......您是否在每次發送消息時打開和關閉套接字?否則我不知道你如何識別消息邊界。另一方面,你有一個ProcessMessage方法有點奇怪,但實現仍然與Stream ...一起工作... – Haplo 2011-04-12 14:19:29

+0

是的,我把那一部分留下了。客戶端在一個打開偵聽器並將客戶端發送到新線程的循環中聲明。 – dbrooklyn 2011-04-12 15:32:29

+0

感謝您的想法,我稍後可能會回到這種方法,但我已經重新設計了客戶端以小信息發送數據,而不是一次發送整個文件。 – dbrooklyn 2011-04-18 13:57:21

回答

0

當你調用ProcessMessage的,並傳遞一個的TcpClient,你是如何初始化這些TcpClient的連接?如果你在沒有多線程的情況下循環執行,那麼你可能會得到類似於你解釋過的結果。當然,我不能確定你是否知道你的客戶端監聽循環設置。

看看這個鏈接:http://www.switchonthecode.com/tutorials/csharp-tutorial-simple-threaded-tcp-server 第二個代碼片段顯示了一個偵聽器循環,它將爲每個客戶端啓動一個新的線程。如果您沒有爲每個客戶端啓動一個新線程,如果一個新線程正在嘗試連接而另一個客戶端正在接收數據,則表示服務器無法響應。

我希望這有助於!

+0

是的,TcpClient是在爲每個連接創建一個新線程的循環中初始化的。謝謝你的例子,我將修改我的代碼,使用'讀取直到0字節收到'模型。這將匹配我發現Google自己搜索的MSDN答案。 – dbrooklyn 2011-04-12 14:49:47

+0

我已經嘗試了兩種做法... while(DataAvailable)方法和讀取直到0字節的方法和do ... while是有效的方法。問題在於通信時間較長,Thread.Sleep(1000)線路的循環​​工作可靠,我希望能夠在沒有睡眠的情況下讀取所有內容,這會降低對較短請求的響應速度。任何想法,我缺少什麼? – dbrooklyn 2011-04-12 17:49:43