2014-02-28 55 views
1

在我的客戶端/服務器應用程序中,我的客戶端將與服務器通信以實現2個功能:客戶端將請求服務器的數據,或者它將發送數據以便服務器保存它。我爲這兩種方法使用了一個套接字,並且要使用的方法由發送的第一個字節定義。如果第一個字節是「1」,它正在請求數據。如果它是「2」,它將發送數據(數據字節在「2」字節後發送)。它非常適合發送數據。但是當我請求數據的時候,只要我不讀取客戶端的套接字流。這就好像我在發送數據後讓客戶端讀取數據一樣,服務器將沒有數據可讀,並且在嘗試讀取數據時只會崩潰。C#套接字:寫入套接字後無法讀取

這裏是我的服務器代碼:

private const int BufferSize = 1024; 
NetworkStream netstream = null; 
byte[] RecData = new byte[BufferSize]; 
int RecBytes; 

try { 
    netstream = clientSocket.GetStream(); 
    int totalrecbytes = 0; 

    using (MemoryStream ms = new MemoryStream()) { 
     //When I get here, there is no data to read 
     while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) { 
      ms.Write(RecData, 0, RecBytes); 
      totalrecbytes += RecBytes; 
     } 

     byte[] bytes = ms.ToArray(); 
     byte b = bytes[0]; 

     switch (b) { 
      case 1: 

      //Here I gather data and put it in "stream" variable 


      byte[] SendingBuffer = null; 
      int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(stream.Length)/Convert.ToDouble(BufferSize))); 
      int TotalLength = (int)stream.Length, CurrentPacketLength, counter = 0; 
      for (int i = 0; i < NoOfPackets; i++) { 
       if (TotalLength > BufferSize) { 
        CurrentPacketLength = BufferSize; 
        TotalLength = TotalLength - CurrentPacketLength; 
       } 
       else 
        CurrentPacketLength = TotalLength; 
       SendingBuffer = new byte[CurrentPacketLength]; 
       stream.Read(SendingBuffer, 0, CurrentPacketLength); 
       netstream.Write(SendingBuffer, 0, (int)SendingBuffer.Length); 
      } 
      netstream.Flush(); 


     } 
     catch (Exception e) { 
      Console.WriteLine("EXCEPTION:\n" + e.ToString()); 
     } 

     break; 
    case 2:    
     //Code to read data 

     break; 
    } 
} 
netstream.Close() 
clientSocket.Close(); 

這裏是我的客戶端代碼:

using (System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient()) { 

    string returnData = ""; 

    IAsyncResult ar = clientSocket.BeginConnect("127.0.0.1", 8080, null, null); 
    System.Threading.WaitHandle wh = ar.AsyncWaitHandle; 
    try { 
     if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5), false)) { 
      clientSocket.Close(); 
      Console.WriteLine("Timeout"); 
      return; 
     } 

     System.Net.Sockets.NetworkStream serverStream = clientSocket.GetStream(); 

     byte b = 1; 

     byte[] outStream = { b }; 
     serverStream.Write(outStream, 0, outStream.Length); 
     serverStream.Flush(); 

     //If I comment following lines, the server can read sent data, but server can't otherwise 
     byte[] RecData = new byte[1024]; 
     int RecBytes; 
     int totalrecbytes = 0; 
     MemoryStream MS = new MemoryStream(); 
     while ((RecBytes = serverStream.Read(RecData, 0, RecData.Length)) > 0) { 
      MS.Write(RecData, 0, RecBytes); 
      totalrecbytes += RecBytes; 
     } 
     serverStream.Close(); 
     clientSocket.Close(); 
     clientSocket.EndConnect(ar); 

    } 
    catch (Exception ex) { 
     Console.WriteLine("Exceção: " + ex.ToString()); 
    } 
    finally { 
     wh.Close(); 
    } 
} 

所以,我怎樣才能將數據發送到服務器,並讀取響應? (我甚至試圖在發送數據後讓線程進入睡眠狀態,但沒有運氣。) 提前致謝。

編輯: 隨着一些調試消息,我發現服務器讀取發送的「1」字節,但不知何故它被卡在while循環內,就像服務器剛剛停在那裏,沒有更多的循環,它不會離開while循環。我在while循環中的控制檯中寫入「loop」之後,並在控制檯中寫入了讀取字節。它寫了一次「循環」和讀取的字節。

回答

1

此代碼讓我擔心:

 //When I get here, there is no data to read 
    while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0) { 
     ms.Write(RecData, 0, RecBytes); 
     totalrecbytes += RecBytes; 
    } 

您正在閱讀,直到客戶端關閉連接(或關閉發送,你不這樣做)。但客戶端只在服務器回覆時關閉。服務器的答覆永遠不會到來。這是一個僵局。

解決方案:讀取單個字節以確定請求命令(b)。

與這個問題無關,您的「封包」發送(NoOfPackets,...)似乎不起任何作用。只需使用Stream.Copy即可。 TCP沒有數據包。

更好的解決方案是放棄您的自定義TCP協議並使用HTTP庫。所有這些擔憂都會消失。代碼中存在各種小問題,這在TCP代碼中很常見。

+0

看來你是對的。要測試它。 – user1531978

+0

完美。就是這樣。謝謝。 – user1531978