3

在接收整数数组时,需要检查接收到的数据的字节数。例如,当接收一个长度为 100 的整数数组时:

int count = 0;
int msg[100];
while(count < 100 * sizeof(int)){
    count += read(fd, msg + count / sizeof(int), 100 * sizeof(int) - count);
}

这是正确的方法吗?read() 会返回一个不是 sizeof(int) 倍数的值吗?如果这不正确,那么接收整数数组的正确方法是什么?

4

3 回答 3

1

您是正确的,read可能不会返回您请求的所有数据,尤其是。如果它连接到网络套接字。read不一定会返回 sizeof(int) 倍数的值。如果您想使用这种(手动)接收数据的方法,我可能会建议您计算字节数而不是 sizeof(int)s(根据您的系统可以是 4 或 8)。比这样做更容易的是使用Protocol Buffers之类的东西,它可以让您为数据包定义数据格式并快速轻松地序列化/反序列化它们。(定义一个只包含整数数组的消息,让 protobuf 处理其他所有事情。)

于 2013-04-19T05:55:53.097 回答
1

在 Linux 上,您可以使用MSG_WAITALL选项 for recv(),这使函数等待完整的给定长度的传入数据。

作为替代方案(在所有平台上工作),您还可以编写一个接收给定字节数的通用接收函数,例如这个(假设套接字未设置为非阻塞;需要包括<stdint.h>):

/// \brief Receives a block of data of the specified size
/// \param sk Socket for incoming data
/// \param data Pointer to input buffer
/// \param len Number of bytes to read
/// \return Number of bytes received (same as len) on success, -1 on failure
int block_recv(const int sk, uint8_t* data, unsigned int len)
{
    int i, j = 0;

    while (len > 0) {
        i = recv(sk, (char*) data, len, 0);
        if (i <= 0) {
            return -1;
        }
        data += i;
        len -= i;
        j += i;
    }

    return j;
}

然后你可以调用它来接收你的整数缓冲区:

if (block_recv(fd, (uint8_t*) msg, sizeof(msg)) != sizeof(msg)) {
    fprintf(stderr, "Error receiving integer buffer...\n");
    // whatever error handling you need...
}
于 2013-04-19T06:41:19.567 回答
0

你是对的 - 不能保证 read 会返回大小是sizeof(int). 您可能收到的最小尺寸是char. 从网络接收整数时还有其他问题,例如字节顺序(这显然也适用于通过网络发送整数),您应该注意这些问题。

由于这些原因,更简单的解决方案是使用 achar[]而不是int[]来存储消息,然后将其复制到int[]. 如果您担心效率,请先向自己证明这是一个瓶颈(分析您的代码),然后再担心优化代码。

此外,如果您正在send通过recv网络进行通信,请注意 TCP 等协议是基于流的,即它们只是发送字符流,您需要实现某种方法来检测消息的结尾并将其格式化为您的需要. 两种常见的方法是要么将消息的长度作为标头发送,要么使用特殊字符(如'\n'表示消息结束)。此外,由于您要发送一个数组,您可以使用类似 '|' 来分离元素。

因此示例消息可以是:“1|100|239|23|\n”

于 2013-04-19T06:46:33.080 回答