为啥 sys socket recv 函数不填充数据但返回字节长度?

Posted

技术标签:

【中文标题】为啥 sys socket recv 函数不填充数据但返回字节长度?【英文标题】:why sys socket recv function don't fill data but return bytes length?为什么 sys socket recv 函数不填充数据但返回字节长度? 【发布时间】:2018-06-14 09:16:11 【问题描述】:

我正在编写一个 C++ 客户端。客户端通过 TCP 协议成功连接到服务器并发送数据。我写了下面的代码来接收数据:

char data[9];
int received_size = recv(fd, data, 9, flags);
std::string str data ;
// str.empty() is true

哪些标志是 MSG_NOSIGNAL。

问题是这行执行后received_size为9但数据长度为零。

【问题讨论】:

你如何确定数据的长度?您是否(错误地)使用 C 字符串或在第一个空字节处停止的类似函数来确定长度? @PaulMcKenzie 在这种状态下我知道我的服务器发送的数据包的长度。我想知道 recv 函数这种奇怪行为的原因 你没有回答我的问题。您如何确定(在代码中)数据为“空”? @PaulMcKenzie 问题代码已更新。 嗯,您的最新编辑回答了这个问题。你停在第一个空字节。接受指针的std::string 的构造函数就是这样做的。所以你的观察是不正确的。 【参考方案1】:

如果recv 正在返回一个值,那么这就是接收到的字节数。

问题在于您使用了错误的函数来确定您收到的数据。无论recv 返回的实际字节数如何,您正在使用的std::string 构造函数将在第一个空字节处停止。

改为使用其他版本的 std::string 构造函数,它采用字节长度:

char data[9];
int received_size = recv(fd, data, 9, flags);
std::string str(data, received_size);

【讨论】:

【参考方案2】:

您期望接收到的数据是零终止的。这是一个错误的期望,因为它可以接收不完整的数据。正确的方法是使用received_size(错误检查后):

std::string str(data, received_size);

这在实际应用中仍然不够。你需要delimit messages somehow。

【讨论】:

【参考方案3】:

如果需要处理零字节,请使用std::vector<unsigned char> 而不是std::string

char data[9];
int received_size = recv(fd, data, 9, flags);
std::vector<unsigned char> str( std::begin(data), std::begin(data)+received_size );
std::cout << str.size() << '\n';

【讨论】:

以上是关于为啥 sys socket recv 函数不填充数据但返回字节长度?的主要内容,如果未能解决你的问题,请参考以下文章

Socket编程时recv函数错误:Transport endpoint is not connected的解决

C语言 recv()函数recvfrom()函数recvmsg()函数

C语言 recv()函数recvfrom()函数recvmsg()函数

有关socket

TCP中 recv和sendf函数

linux send与recv函数详解