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);
这根本不起作用。 有人能给我一个正确方向的推动吗?
通常你会先发送长度。 两端应该就长度的长度达成一致 – 例如,您可能乐意使用固定的4字节长度前缀作为二进制:
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个字节以获得长度。 对于阅读,接收器应注意不要读取太多数据。 一种方法是使用限制流 – 例如, 此类可用于获取不会读取太多的Stream。
如果您不希望总是发送4个字节的开销,那么可能会有一些更有趣的编码 – 例如,使用msb作为延续块。
有关信息, protobuf-net是一个围绕谷歌的“协议缓冲”基于消息的格式设计的二进制序列化器。 它为您处理了很多细节,如果您不想花费大量时间编写序列化代码,可能会感兴趣。 QuickStart项目中有套接字的示例, 例如此处
而不是data.Length
,尝试:
writer.Write(chr(data.Length) + data);
这将在每个数据块前面加上一个字节,表示其长度(最长255个字节)。 按照您的要求,这只是一个轻推。 🙂
更新:我只记得C#是所有Unicode和东西,所以chr()可能会给你多个字节。 调整以适应。
我想这应该这样做:(我假设你的数据是一个字符串)
Stream stream = tcpClient.GetStream(); 编码编码= Encoding.GetEncoding(“编码名称”); byte [] bytes = encoding.getBytes(data); stream.Write(BitConverter.GetBytes((短)bytes.Length),0,2); //希望数据不会超过64k stream.Write(字节,0,bytes.Length);
当你说“这根本不能很好地工作”时,我会特别好奇什么是行不通的。 它们是套接字两端的.NET应用程序吗? 如果是这样,请忽略此答案。 如果没有,那么问题可能是整数的字节顺序? 一个小端和大端问题? 这个post在这里讨论它:
http://bytes.com/forum/thread225649.html
如果两端都不是.NET的另一个问题可能是另一端需要ANSI字符串,而您正在发送Unicode。
您也可以,如果您想保留它的明文,请指定特定的最大大小,并通过string.Format填充数字。 (例如,假设只允许4个字符的长度)这避免了有用数据流中的数字问题,并简化了解码。
最后一个明文解决方案是在长度和数据之间放置一个特定字符,例如 – ,然后一次抓取一个字符,直到你达到减号,解码检索到的字符串(忽略当然的减号),然后用它来确定剩余字符串的长度,以及您需要更改的输出代码,以便在其间添加该字符。
使用WriteLine而不是Write,ReadLine而不是Read …
如果您正在谈论发送纯文本消息,请在消息末尾添加换行符。 然后,读取字节,直到遇到此换行符并将字节转换为字符串。 为方便起见,任何System.IO.StreamReader和System.IO.StreamReader都在单个方法(WriterLine或ReadLine)writer.WriteLine(“Line to send”)中实现此行为; string lineSent = reader.ReadLine();