C++从套接字读取并存入std::string

11

我正在编写一个使用c sockets的c++程序。我需要一个接收数据并返回字符串的函数。我知道以下代码不会起作用:

std::string Communication::recv(int bytes) {
    std::string output;
    if (read(this->sock, output, bytes)<0) {
        std::cerr << "Failed to read data from socket.\n";
    }
    return output;
}

由于read()函数需要一个字符数组指针作为参数。在这里,最好的返回字符串的方法是什么?我知道理论上可以将数据读入字符数组中,然后将其转换为字符串,但我觉得这样很浪费。有更好的方法吗?
*如果有更合适的替代方案,我并不介意使用其他东西而不是read()
这是pastebin上的所有代码,它应该在一周内过期。如果那时候我还没有答案,我会重新发布它:http://pastebin.com/HkTDzmSt [更新]
我还尝试使用&output[0],但输出包含以下内容:
jello!
[insert a billion bell characters here]

"jello!"是发送回套接字的数据。


2
c_str() 是 const 的,你不能这样做。只需读入缓冲区,然后将其复制到字符串中即可。 - billz
1
output[0] 返回对第一个字符的引用。您需要一个指针来写入套接字,因此您需要获取该引用的地址。由于字符串中的字符在内存中是连续的,因此您可以这样做。&output将指向字符串对象而不是您可以写入的缓冲区。 - Eric Fortin
@EricFortin 我正在使用netcat测试套接字。我发送给程序的所有内容都应该是jello!\n - 735Tesla
第三个参数是可以读取的最大值。您可以读取较少的内容(即短读取)。在我看来,这是不太有趣的方面。当您意外地将更多内容放入原始字符串中,超过了分配的长度或字符串对象在其长度变量中知道的长度时会发生什么? - Duck
@EricFortin 我会编写一个Python程序来测试它,因为这将非常简单。 - 735Tesla
显示剩余13条评论
1个回答

8

以下是一些能帮助你实现需求的函数。它假定你只会从套接字的另一端接收 ASCII 字符。

std::string Communication::recv(int bytes) {
    std::string output(bytes, 0);
    if (read(this->sock, &output[0], bytes-1)<0) {
        std::cerr << "Failed to read data from socket.\n";
    }
    return output;
}

或者

std::string Communication::recv(int bytes) {
    std::string output;
    output.resize(bytes);

    int bytes_received = read(this->sock, &output[0], bytes-1);
    if (bytes_received<0) {
        std::cerr << "Failed to read data from socket.\n";
        return "";
    }

    output[bytes_received] = 0;
    return output;
}

当输出字符串时,请确保使用cout << output.c_str(),因为字符串覆盖了operator<<并跳过不可打印的字符直到达到大小。最终,您也可以在函数末尾调整大小以接收大小并能够使用正常的cout
如评论中所指出的那样,首先发送大小也是一个好主意,以避免字符串类可能不必要的内存分配。

我仍然得到与我在上一条评论中链接的相同输出。有趣的是,似乎响铃字符大约等于从1024(我当前用作“字节”的参数)减去“jello!”的长度。 - 735Tesla
1
@735Tesla 你应该先发送字符串的长度。然后在接收时,首先读取该长度以知道接下来要读取多少内容。通过使用固定长度进行接收,你将会一直等待或者读取垃圾数据到你的字符串中。 - François Moisan
@FrançoisMoisan 谢谢。我没有想到过这样做。但是还有一种动态接收输入的方法吗? - 735Tesla
尝试像这样打印输出字符串:cout << output.c_str() << endl; 字符串重写运算符<<并跳过值为0的字节,直到达到大小为止。 - Eric Fortin
@EricFortin 那个方法有效了!谢谢你!你能把它加到你的答案里吗? - 735Tesla
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接