如何通过 linux 套接字将 UTF-8 文本放入 std::string
How to put UTF-8 text into std::string through linux sockets
我制作了一个简单的 C++ 服务器程序,只要我将它与像 telnet 这样的简单工具一起使用,它就可以正常工作,但是当我使用例如 .Net (C#) 时,它会连接到它并向它发送一些字符串, 文本有些损坏。我在 C# 端尝试了多种编码,唯一的结果是它以不同的方式损坏了。
我认为主要问题在于此函数,该函数旨在从套接字读取一行文本:
std::string Client::ReadLine()
{
std::string line;
while (true)
{
char buffer[10];
read(this->Socket, buffer, 9);
int i = 0;
while (i < 10)
{
if (buffer[i] == '\r')
{
i++;
continue;
}
if (buffer[i] == '[=12=]')
{
// end of string reached
break;
}
if (buffer[i] == '\n')
{
return line;
}
line += buffer[i];
i++;
}
}
return line;
}
这是程序到终端的简单输出,当我使用 telnet 向它发送字符串 "en.wikipedia.org" 时,我看到:
Subscribed to en.wikipedia.org
当我使用使用此代码打开流编写器的 C# 时
streamWriter = new StreamWriter(networkStream, Encoding.UTF8);
我明白了:
Subscribed to en.wiki,pedia.org,
当我在没有 UTF-8 的情况下使用它时(因此使用默认的 .net 编码,IDK 是什么)
streamWriter = new StreamWriter(networkStream);
我明白了:
Subscribed to en.wiki�pedia.org�
然而,这两种情况都是错误的。仅使用标准 C++ 和 linux 库实现此目的的最简单方法是什么? (没有 boost 等——我可以使用一些框架来做到这一点,比如 Qt、boost 等,但我想了解这一点)。完整代码@http://github.com/huggle/XMLRCS
UTF-8 字符串只是一系列单字节,基本上只是 wnat std::string
应该处理的。您还有另外两个问题:
首先是你实际上并没有检查实际读取了多少个字符,你总是循环超过十个字符。由于您没有遍历实际读取的字符数(并且不检查错误或连接结束),您可能会在缓冲区中读取超出 read
写入的数据并且您有 undefined behavior.
第二个问题与第一个问题有点相关,那就是你有一个十个字符的缓冲区,你将 最多 九个字符读入缓冲区,然后遍历缓冲区中的 所有十个 个字符。这样做的问题是,由于您最多只能读取九个字符,因此第十个字符将始终未初始化。因为缓冲区中的第十个条目始终未初始化,所以它的值将是不确定的,读取它会再次导致未定义的行为。
我制作了一个简单的 C++ 服务器程序,只要我将它与像 telnet 这样的简单工具一起使用,它就可以正常工作,但是当我使用例如 .Net (C#) 时,它会连接到它并向它发送一些字符串, 文本有些损坏。我在 C# 端尝试了多种编码,唯一的结果是它以不同的方式损坏了。
我认为主要问题在于此函数,该函数旨在从套接字读取一行文本:
std::string Client::ReadLine()
{
std::string line;
while (true)
{
char buffer[10];
read(this->Socket, buffer, 9);
int i = 0;
while (i < 10)
{
if (buffer[i] == '\r')
{
i++;
continue;
}
if (buffer[i] == '[=12=]')
{
// end of string reached
break;
}
if (buffer[i] == '\n')
{
return line;
}
line += buffer[i];
i++;
}
}
return line;
}
这是程序到终端的简单输出,当我使用 telnet 向它发送字符串 "en.wikipedia.org" 时,我看到:
Subscribed to en.wikipedia.org
当我使用使用此代码打开流编写器的 C# 时
streamWriter = new StreamWriter(networkStream, Encoding.UTF8);
我明白了:
Subscribed to en.wiki,pedia.org,
当我在没有 UTF-8 的情况下使用它时(因此使用默认的 .net 编码,IDK 是什么)
streamWriter = new StreamWriter(networkStream);
我明白了:
Subscribed to en.wiki�pedia.org�
然而,这两种情况都是错误的。仅使用标准 C++ 和 linux 库实现此目的的最简单方法是什么? (没有 boost 等——我可以使用一些框架来做到这一点,比如 Qt、boost 等,但我想了解这一点)。完整代码@http://github.com/huggle/XMLRCS
UTF-8 字符串只是一系列单字节,基本上只是 wnat std::string
应该处理的。您还有另外两个问题:
首先是你实际上并没有检查实际读取了多少个字符,你总是循环超过十个字符。由于您没有遍历实际读取的字符数(并且不检查错误或连接结束),您可能会在缓冲区中读取超出 read
写入的数据并且您有 undefined behavior.
第二个问题与第一个问题有点相关,那就是你有一个十个字符的缓冲区,你将 最多 九个字符读入缓冲区,然后遍历缓冲区中的 所有十个 个字符。这样做的问题是,由于您最多只能读取九个字符,因此第十个字符将始终未初始化。因为缓冲区中的第十个条目始终未初始化,所以它的值将是不确定的,读取它会再次导致未定义的行为。