gpt4 book ai didi

c# - 异步套接字,接收字符串消息

转载 作者:行者123 更新时间:2023-11-30 22:36:54 25 4
gpt4 key购买 nike

晚上好,提前写了这么多,但我不知道错误在哪里...

我的客户端应用程序从服务器异步接收。我想一次传输一堆东西(数组的内容,几百个字节)。

我希望服务器能够发送“命令”,并在客户端根据这些命令执行操作,例如,如果来自服务器的消息为 "print_hello",它应该调用一个打印 hello 的函数。

现在,我的理解是当异步接收数据时,我无法知道发送了多少数据(或者是否发送了比我预期更多的数据),所以我需要将所有数据存储在一个缓冲区,并且当收到“命令结束”(例如,'!')标志时,它应该知道调用该函数。

到目前为止,这对我来说很有意义,但我在实现它时遇到了麻烦。在我的 DataReceived 回调函数中,我有这段代码:

Console.WriteLine("Raw data: {0}", data));
mainBuffer += data;
Console.WriteLine(mainBuffer);

mainBuffer 声明为 volatile static string mainBuffer = "";第一行打印正确,并按预期遍历所有数据。然而,当我打印出 mainBuffer 时,它只会打印出我收到的第一组数据,其余的不会添加到缓冲区中。

什么会导致这种情况?线程安全问题?我不是在读 mainBuffer 的最新值吗?我不能使用断点来调试它。

示例输出:

Raw data: ABC
ABC
Raw data: DEF
ABC
RAW data: GHI
ABC

小更新,我也尝试使用 volatile static int,它会在每次 DataReceived() 后递增并正确打印。然而,该字符串仍然没有得到更新。

最佳答案

这是你的问题“乱七八糟的代码行!”:

//of course the problem has noting to do with the string being volatile...
private volatile string mainBuffer = string.Empty;

byte[] buffer = new byte[1024];

while (networkStream.Read(buffer, 0, buffer.Length) > 0)
{
string data = System.Text.Encoding.UTF8.GetString(buffer);
Console.WriteLine("Raw data: {0}", data));
mainBuffer += data;
Console.WriteLine(mainBuffer);
}

自然地,此代码的输出将如您之前提到的那样。这是正在发生的事情:

C# 中的 string 类是一个 char 数组,以指向数组中第一个 char 的指针开始,以特殊的 "终端”字符\0
当您创建一个包含 n 索引的字节数组时,它会用 byte 的默认值填充数组的所有索引,即 0。但是 0 正好等于终端字符 \0

byte b = (byte)`\0`;\\the value of b will be 0

因此,当您调用 Read(buffer) 时,该方法不会修剪 缓冲区以刚好适合 读取的数据。所以如果缓冲区大小“这里 1024”大于读取的数据,缓冲区的所有剩余字节将等于终端字符 '\0',因此生成的字符串的字符数组将为 ABC\0\0\0\0... 到索引 1024。当您向其中添加字符串 DEF 时,它会将其添加到 char 数组的最后一个索引“在最后一个 \0 之后”,char 数组则为 ABC\0\0\0\0...DEF,但由于 DEF 是在终端 char( s) 因此 Console.Write 将忽略第一个 \0! 之后的所有内容。

另请注意,在调试时,如果将鼠标指向 mainBuffer 变量,您将看到它包含的实际数据可能类似于 ABC\0\0\0\0。 .DEF\0\0\0\0..GHI

然而,要解决该问题并仅生成可靠的字符串,请获取实际读取的字节并仅从中生成字符串。所以:

int dataRead = 0;

while ((dataRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
List<byte> actualBuffer = (new List<byte>(buffer)).GetRange(0, dataRead);

string data = System.Text.Encoding.UTF8.GetString(actualBuffer.ToArray());
Console.WriteLine("Raw data: {0}", data));
mainBuffer += data;
Console.WriteLine(mainBuffer);
}

在这里很遗憾地提到您应该考虑使用 StringBuilder而不是 string

关于c# - 异步套接字,接收字符串消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6774887/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com