繁体   English   中英

在单个 recv() 方法期间从套接字读取所有数据

[英]Read all data during single recv() method from a socket

我正在尝试使用套接字编程连续读取数据。 我使用 recv() 接收套接字上的数据。 我将它存储在缓冲区中。 recv() 返回读取的字节数。 以下是片段:

while (true) {
        try {
            char buff[2048];
            int bytes = recv(sockfd, buff, 2048, 0);
            buff[bytes] = '\0';
            cout << strlen(buff) << endl;
            cout << bytes << endl;
            cout << "-------" << endl;
        } catch (const char *e) {
        }
    }

以下是output的代码:

1
1204
-------
1
1390
-------
1
25
-------
1
1204
-------

通过 recv() 方法接收到的字节数是正确的,但我无法读取确切的数据数。 如何读取在单个 recv() 方法期间捕获的所有数据?

您需要像文档中那样将正确的标志传递给 recv 。 基于: https://man7.org/linux/man-pages/man2/recv.2.html有标志 MSG_WAITALL (因为 ZEDC9F0A5A5D57797BF368E37326474 做什么)

调用看起来像:

int bytes = recv(sockfd, buff, 2048, MSG_WAITALL);

除非您确定只收到文本,否则通过 strlen 检查接收字节的长度是不好的。

您可以创建一个std::string_view指向读取的数据。

while (true) {
    char buff[2048];
    int bytes = recv(sockfd, buff, 2048, 0);
    if (bytes >= 0) {
        std::string_view read { buff, bytes };
        std::cout << read << std::endl;
        std::cout << "-------" << std::endl;
    } // else?
}

function strlen会将buff的内容视为以 null 结尾的字符串并返回该字符串的长度。

在行

buff[bytes] = '\0';

您在数据末尾写了一个 null 终止字符。 这样,您就确保了数据以空值结尾。

但是, recv读取的字节可能包含值为0的字节。 function strlen将无法区分这样的字节和实际的终止 null 字符。 它将简单地返回值为0的第一个字节的 position 的索引。

这就是为什么表达式strlen(buff)与数据的实际长度不对应的原因。

因此,您不应在二进制数据上使用 function strlen function 仅用于文本数据,它不能包含值为0的字符,除了标记字符串的结尾。

不应使用strlen来确定数据的长度,而应仅使用recv返回的值(已存储在变量bytes中)。 只要记住这个值,就永远知道长度,所以不需要用终止符 null 来标记数据的结尾。

假设recv返回正值(负数表示失败),你会找到数组buff中的所有数据, recv的返回值将指定数据的长度。 例如,如果您想打印在对recv的 function 调用中收到的所有数据,则可以在recv function 调用之后立即编写以下内容:

for ( int i = 0; i < bytes; i++ )
    cout << hex << setw(2) << setfill( '0' ) << static_cast<int>(buff[i]) << ' ';

请注意,您必须在程序开头添加#include <iomanip>才能使该行生效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM