2008-10-15 28 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();