如何在C/C++;插座

如何在C/C++;插座,c,sockets,recv,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); } int count=0; int msg[100]; 而(计数小于100*sizeof(int)){ 计数+=读取(fd,m

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

int count = 0;
int msg[100];
while(count < 100 * sizeof(int)){
    count += read(fd, msg + count / sizeof(int), 100 * sizeof(int) - count);
}
int count=0;
int msg[100];
而(计数小于100*sizeof(int)){
计数+=读取(fd,msg+count/sizeof(int),100*sizeof(int)-计数);
}
这条路对吗?read()是否会返回一个不是sizeof(int)的倍数的值?
如果这不正确,接收整数数组的正确方法是什么

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

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

在替代方案中(在所有平台上工作),您还可以编写一个通用接收函数,接收给定数量的字节,如下面的(假定套接字未设置为非阻塞;需要包含
):


你说得对-不能保证read将返回大小为
sizeof(int)
倍数的数据。 您可能收到的最小大小为
字符
。 还有其他一些问题,比如endianness,你应该注意的是什么时候(这显然也适用于)

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

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


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

应该注意,如果出现错误或中断,或者如果即将阻塞并已被传递,非阻塞套接字
read()
也可能返回-1,这在OP的源代码中没有考虑,因此这个slatter案例将彻底破坏算法。另外,不考虑
read()
返回
0
的情况,即连接的另一端关闭,这将导致无限循环。
/// \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...
}