如何通过 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.

第二个问题与第一个问题有点相关,那就是你有一个十个字符的缓冲区,你将 最多 九个字符读入缓冲区,然后遍历缓冲区中的 所有十个 个字符。这样做的问题是,由于您最多只能读取九个字符,因此第十个字符将始终未初始化。因为缓冲区中的第十个条目始终未初始化,所以它的值将是不确定的,读取它会再次导致未定义的行为。