如何在C / C ++套接字中接收整数数组?

时间:2013-04-19 05:46:51

标签: c sockets recv

在接收整数数组时,需要检查接收数据的字节数。 例如,当接收长度为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)的倍数的值吗? 如果这不正确,接收整数数组的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

在Linux上,您可以使用MSG_WAITALL 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...
}

答案 2 :(得分:0)

你是对的 - 不能保证read会返回大小为sizeof(int)倍数的数据。 您可能收到的最小尺寸为char。 当receiving integers from across a network(显然也适用于sending integers across a network)时,您应该注意其他问题,例如字节序。

出于这些原因,更简单的解决方案是使用char[]代替int[]来存储邮件,然后将其复制到int[]。如果您担心效率,请在担心优化代码之前向自己证明这是一个瓶颈(描述您的代码)。

此外,如果您sendrecv穿过网络,请注意TCP之类的协议是基于流的,即它们只是发送字符流而您需要以某种方式实现检测消息的结束并根据您的需要对其进行格式化。两种常见的方法是将消息的长度作为标题发送,或者使用像'\n'这样的特殊字符来表示消息的结束。此外,由于您正在发送数组,您可以使用类似“|”的内容分开元素。

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