通过网络发送字符串,客户端仅获取一部分

本文关键字:客户端 获取 一部分 字符串 网络 | 更新日期: 2023-09-27 18:36:50

我正在开发客户端/服务器应用程序。
服务器有时会向所有连接的客户端发送字符串。

为此,我定义了一个数据包:
字节 <- 数据包 ID
整数 <- 字符串的长度byte[] 包含字符串的 <- 字节数组

现在我如何发送这个数据包:

byte[] buf = { ID };
buf = buf.Concat(BitConverter.GetBytes(StringData.Length)).ToArray();
buf = buf.Concat(Encoding.UTF8.GetBytes(StringData)).ToArray();
stream.Write(buf, 0, buf.Length);
有时

字符串很小(大约 200 字节),但有时它有点大(>20k 字节)。通常,较小的数据包在客户端读取它们时没有问题,但客户端仅部分接收较大的数据包。
所以客户端的典型场景:

packet id -> 0x01
length -> 20000
string -> "this is an example stri"

我知道"这是一个示例字符串"不是 20000 字节长,但它只是一个示例。
在我的例子中,字符串是一个序列化的 JObject (Json.Net)。

在客户端,我像这样读取数据包:

byte[] buf = new byte[1];
stream.Read(buf, 0, buf.Length);
// Some packet id evaluation
buf = new byte[4];
stream.Read(buf, 0, buf.Length);
int length = BitConverter.ToInt32(buf, 0);
buf = new byte[length];
stream.Read(buf, 0, length);
string jsonString = Encoding.UTF8.GetString(buf, 0, length);

真的不知道我做错了什么。
任何建议在哪里查找错误或我在发送数据时做错了什么?

提前感谢!

通过网络发送字符串,客户端仅获取一部分

代码有两个问题:

首先,您使用字符串的长度而不是数据包中编码数据的长度。首先转换字符串,以便您可以使用数据包中的长度:

byte[] data = Encoding.UTF8.GetBytes(StringData);
byte[] buf = { ID };
buf = buf.Concat(BitConverter.GetBytes(data.Length)).ToArray();
buf = buf.Concat(data).ToArray();

其次,Read 方法不保证它返回请求的字节数。它可能会在缓冲区中放置较少的字节,并返回缓冲区中实际放置的字节数。

使用 Read 调用的返回值检查是否需要多次调用它来获取数据。例:

buf = new byte[4];
int offset = 0;
while (offset < buf.length) {
  int len = stream.Read(buf, offset, buf.Length - offset);
  offset += len;
}

注意:此实现不会处理流过早结束的情况。然后Read方法将返回零,代码进入永恒循环。您可能希望创建一个用于从流中读取的方法,以便在其中处理所有可能的错误。

我不能保证这会起作用,但试一试读取您的数据:

var ms = new System.IO.MemoryStream();
byte[] buffer = new byte[4096];
int bytesRead = 0;
do
{
    bytesRead = stream.Read(buffer, 0, buffer.Length);
    ms.Write(buffer, 0, bytesRead);
}
while (stream.DataAvailable);
string jsonString = System.Text.Encoding.UTF8.GetString(ms.ToArray());

根据需要进行调整。让我知道它是如何工作的。