2008-10-15 56 views
2

還挺長的頭銜,但反正...C#流式套接字,如何分離消息?

我一直在尋找在這些例子中,特別是在寫作部分和閱讀郵件的大小,以字節流
http://doc.trolltech.com/4.4/network-fortuneclient-client-cpp.html
http://doc.trolltech.com/4.4/network-fortuneserver-server-cpp.html

但我似乎無法弄清楚在C#中。

StreamWriter writer = new StreamWriter(tcpClient.GetStream()); 
writer.Write(data.Length + data); 

這根本不起作用。有人能給我一個正確的方向嗎?

回答

2

通常你會先發送的長度。

byte[] data = ... 
    int len = data.Length; 
    byte[] prefix = Bitconverter.GetBytes(len); 
    stream.Write(prefix, 0, prefix.Length); // fixed 4 bytes 
    stream.Write(data, 0, data.Length); 

顯然,調用者需要做同樣的 - 即讀第4:例如,你可能會很高興的使用固定的4字節長的前綴爲二進制 - 兩端應該在什麼長度樣子同意字節來獲得長度。爲了閱讀,接收機應注意不要讀取太多的數據。一種方法是使用限制流 - 例如,this class可用於獲取不會讀取太多的Stream。

如果你不想總是發送4個字節的開銷,那麼一些更有趣的編碼是可能的 - 例如,使用msb作爲延續塊。

有關信息,protobuf-net是圍繞Google的「協議緩衝區」消息格式設計的二進制序列化程序。它爲您處理了許多細節,如果您不想花費大量時間編寫序列化代碼,可能會感興趣。在QuickStart項目中有套接字的例子,for example here

+0

我應該怎麼做來接收數據? – deem 2012-04-02 09:55:46

1

代替data.Length,嘗試:

writer.Write(chr(data.Length) + data); 

這將前綴的每一個數據塊具有一個字節表示其長度(最多255個字節長)。按照你的要求,這只是一個微調。 :)

更新:我只記得C#是所有的Unicode和東西,所以CHR()可能會給你多個字節。調整以適應。

1

我想這應該這樣做: (我假設你的數據是一個字符串)

 
Stream stream = tcpClient.GetStream(); 
Encoding encoding = Encoding.GetEncoding("encoding name"); 

byte[] bytes = encoding.getBytes(data); 

stream.Write(BitConverter.GetBytes((short)bytes.Length),0,2); // hope data isn't longer that 64k 
stream.Write(bytes,0,bytes.Length); 
0

當你說「這根本不能很好地工作」時,我會特別好奇什麼不起作用。它們是套接字兩端的.NET應用程序嗎?如果是這樣,請忽略此答案。如果不是,那麼問題可能是整數的字節順序?一個小端到大端的問題?這裏這個線程討論它:

http://bytes.com/forum/thread225649.html

http://books.google.com/books?id=2zT5b2BS1OUC&pg=PA64&lpg=PA64&dq=c%23+sockets+integers+byte+ordering&source=web&ots=_ISzZZ6HHT&sig=tUHdNT0NGv0uxusmHG9YjFw6j9k&hl=en&sa=X&oi=book_result&resnum=2&ct=result

如果兩端都沒有.NET可能是另一端期望ANSI字符串,而要發送的Unicode另一個問題。

0

如果你想保留它的明文,你也可以指定一個特定的最大尺寸並通過string.Format填充數字。(例如,只允許長度爲4個字符)這樣可以避免有用數據流中的數字問題,並簡化了解碼過程。

最終的純文本解決方案是在長度和數據之間放置一個特定的字符,例如 - ,然後一次抓取單個字符,直到您找到一個負數,解碼檢索到的字符串(忽略當然減號),然後使用確定剩餘字符串的長度,以及只需更改其輸出代碼以在其間添加該字符即可。

0

使用的WriteLine,而不是寫,的ReadLine,而不是讀...

如果你在談論發送純文本郵件,在郵件的末尾添加換行符。然後,讀取字節,直到遇到此換行符並將字節轉換爲字符串。 爲了您的方便,任何System.IO.StreamReader和System.IO.StreamReader以單一方法(WriterLine或ReadLine)實現此行爲 writer.WriteLine(「Line to send」); string lineSent = reader.ReadLine();