我在服务器上有两个应用程序,在客户端上有一个应用程序。
在服务器端,我写这样的流。
NetworkStream stream = client.GetStream();
byte[] msg = System.Text.Encoding.ASCII.GetBytes(messageSent);
stream.Write(msg, 0, msg.Length);
stream.Write(msg, 0, msg.Length);
我在逐个流中写了多个字符串。弦的长度是可变的,达到最大长度约为500
问题:
如何在块中以客户端方式阅读
有时我会得到组合字符串
就像我发送A,B,C
一样在客户端,我收到了A,BC
我是这样的客户:
bytes = stream.Read(data, 0, data.Length);
感谢任何帮助。
答案 0 :(得分:5)
是的,你有一个流 - 只是一个字节序列 - 但你把它视为不是一个流;好像它是一个面向消息的协议。
从根本上说,通过简单的基于流的通信,没有任何固有的可以将流分解为消息。如果你想这样做,你需要在顶部构建一个层。有三种常见的方法:
其中第二个可能是最简单的,但有一个限制,你需要知道在开始发送之前消息有多大。第三个选项通过具有可变数量的块来绕过它。如果可能的话,我个人会避免使用第一个选项 - 除非你有一些自然的“消息结束”令牌,你永远不想将其作为数据包含在消息中,你必须开始研究逃避计划,这是一个痛苦......而且也很难读取数据。
当然,你不必从头开始做所有这些。如果你的两端都有.NET,你可以使用支持长度前缀字符串的BinaryReader
和BinaryWriter
,并且还有很多序列化框架,通常以某种形式处理这个或者其他。 (我个人的偏好是Protocol Buffers,因为它是高效的,独立于平台的,以及我在工作中使用的东西。有两个常见的.NET端口 - one by myself和one by Marc Gravell。)
答案 1 :(得分:2)
顾名思义,您正在使用的是一个流。一方的电话Write
与另一方的电话Read
之间无法保证1-1对应。
发送消息的一种常用方法是首先发送消息长度(例如,转换为4字节的int),然后发送消息。
然后(在接收方),读取该长度,(如果需要)分配该大小的缓冲区,然后重复调用Read
,直到填充缓冲区为止。
答案 2 :(得分:2)
流只是一个字节序列。除了您创建的块之外,没有块的概念。您需要发明一些附加机制来了解每个块的开始/结束位置。有多种常见的方法可以做到这一点:
1
意味着"" 1个字节读取",65个是A
等。