【问题标题】:Send string over network, Client only gets a part通过网络发送字符串,客户端只得到一部分
【发布时间】:2013-10-24 18:10:26
【问题描述】:

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

为此,我定义了一个数据包:
字节 int

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

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);

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

提前致谢!

【问题讨论】:

  • 当这里没有 JSON 工作时,你为什么要打电话给你的 string jsonString
  • 在真正的应用程序中,我发送 json 字符串,所以我也称它为 jsonString。
  • 在下面查看我的答案,让我知道它是如何工作的。
  • 关于 TCP 的一个常见误解是您将收到您发送的内容。您可以这样做,但仅限于数据的顺序。然而,“分组”可能会因软件和/或硬件沿途数据路由的方式而大不相同。数据可以组合在一起或分解到达另一端。当您调用 Read() 时,它会返回返回的字节数,您可以使用它来提取缓冲区中数据的“有效”部分(可能未“满”)。反复将数据附加到 master 缓冲区中,然后根据您的协议检查“消息”。

标签: c# networking


【解决方案1】:

代码有两个问题:

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

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 方法将返回零,代码进入一个永恒循环。您可能想要创建一个用于从流中读取的方法,您可以在其中处理所有可能的错误。

【讨论】:

  • 就是这样! :) 特别是使用编码字节 [] 的长度是我没有想到的。无论如何,在进行此类操作时,我又学到了一些要记住的新东西。谢谢! :)
【解决方案2】:

我不能保证这会奏效,但请试一试阅读您的数据:

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());

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2014-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多