2014-09-03 46 views
0

我有兩個軟件,一個是服務器,另一個是客戶端界面。NetworkStream寫不新線,如果不是線程睡

在我的服務器我正在和處理請求,然後通過我寫了一個方法返回一個字符串「回覆」

public static void reply(string buffer, NetworkStream stream) 
    { 
     stream.Write(Encoding.ASCII.GetBytes(buffer), 0, buffer.Length); 
    } 

我遇到的問題是,例如,如果我是做下面的代碼

for(int i = 0; i<5; i++){ 
reply("SOME REPLY", stream); 
} 

上面的代碼會寫隨機newlined線回客戶端這樣的:

SOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLYSOME REPLYSOME REPLY 
SOME REPLYSOME REPLY 
SOME REPLY 
SOME REPLY 

如果我在forloop中放置了一個200ms的Thread.Sleep調用,它將正確地更新響應。 在客戶端下面的代碼是如何我們正在從服務器讀取打印到控制檯:

 Byte[] bytes = new Byte[256]; 
     NetworkStream stream = endpoint.GetStream(); 
     int i; 
     while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
     { 
      Console.WriteLine(System.Text.Encoding.ASCII.GetString(bytes, 0, i)); 
     } 

回答

2

你的問題是,客戶端不發送一個換行符,所以服務器基本上沒有線索在哪裏放置換行符。 事實上,你得到'一些'換行符,與流的使用方式有關,當你調用read時,NetworkStream將總是讀取任何可用的數據,或者等到有一些數據可用時;不能保證你收到的是你想要的。 您可以從應用程序的服務器端的流中讀取所有數據,然後添加一個換行符(由於Console.WriteLine調用),然後繼續閱讀消息的下一部分。

我想最簡單的方法來解決,這是簡單的通話reply("SOME REPLY", stream);改變reply("SOME REPLY" + Environment.NewLine, stream);,然後在服務器端的Console.WriteLine電話更改爲簡單Console.Write電話。

處理分段消息或緩衝消息的更好但稍微複雜的方法是始終在客戶端發送消息前的「字節數」,以便服務器知道要讀取多少字節添加一個新行:

僞代碼:

Client => Send([number of bytes] + [data]) 
Server => Read([number of bytes] (Field)) 
Server => Read([data]) until received bytes count == [number of bytes] 
+0

這是使用['BinaryWriter'](http://msdn.microsoft.com/en-us/library/yzxa6408(v = vs.110).aspx)的地方。它會爲您寫入前導長度字節。 – 2014-09-03 16:04:02

+0

謝謝,我實際上嘗試過「\ n」沒有成功,但我不相信我轉而使用「writ」而不是「writeline」。你的固定工作很好。 – user2887749 2014-09-03 19:41:35

+0

如果您使用的是Windows,\ n需要\ r \ n - 特別是在.NET中 - 請參閱Environment.NewLine屬性。 – t0yk4t 2014-09-03 20:47:27

1

服務器不是在所有寫任何換行到客戶端,它是文本,它讀取的每個塊之後插入新行客戶端。

當網絡流出現問題時,客戶端將讀取當前在緩衝區中的所有內容,然後寫入換行符。在處理那部分數據時,服務器可能有時間將若干段文本寫入流,因此下次客戶端從流中讀取時,它可以同時獲取多個文本。

分離來自服務器的文本的唯一情況是時間差距很小,客戶端並沒有注意到,因爲它在忙於處理之前讀取的內容。你可以試着讓代碼注意那些時間差距,但這遠非一個強大的解決方案。

如果你想分離文本片段,你應該發送一些實際的流,客戶端可以可靠地拿起。如果你只是想在文本之間換行,那麼從服務器發送換行符,然後客戶端可以只寫出它得到的內容而不添加任何內容。