无法使用C中的套接字接收大型数组

时间:2018-06-24 16:05:58

标签: c sockets

我正在使用C中的POSIX套接字将一个树莓派的大小的整数数组发送到另一个树莓派。我正在从一个pi编写一个大小为131072的整数数组,write命令的返回值显示所有131072值都已被写入。 ret = write(socket, &array, sizeof(array))使用相同的接收方法ret = read(socket, &array, sizeof(array))表示未读取所有已发送的值,而是正确读取的值的数量也不是恒定的,而是在10000到20000之间变化。

我试图在循环中使用read函数,在每次循环迭代中我都读取整数

for(int i =0; i<131072; i++){
ret = read(socket, &value, sizeof(value));
data[i] = value;}

我能够毫无错误地接收所有值。

2 个答案:

答案 0 :(得分:0)

基础协议(可能是TCP和IP)将数据拆分为数据包,这些数据包可能作为单独的数据块到达接收应用程序。从理论上讲,read()可能会单独接收每个字节(即,当调用2000次时,每次返回1)。您的应用程序需要能够使用它。

答案 1 :(得分:0)

您可能需要使用与此类似的代码:

multi-rw.h

#ifndef JLSS_ID_MULTI_RW_H
#define JLSS_ID_MULTI_RW_H

#include <sys/types.h>

extern ssize_t multi_read(int fd, char *buffer, size_t nbytes);
extern ssize_t multi_write(int fd, const char *buffer, size_t nbytes);

#endif

multi-rw.c

不幸的是,测试代码块必须位于活动函数之前,但这是必需的(并且测试代码是必需的-至少,我觉得它非常有用并且令人放心)。我想它可以进入一个单独的头文件(multi-rw-test.h或其附近),该文件将有条件地包括在内;最好用SO表示,否则就是另一个需要担心的文件。

#include "multi-rw.h"
#include <unistd.h>

#ifdef TEST

#ifndef MAX_WRITE_SIZE
#define MAX_WRITE_SIZE 64
#endif
#ifndef MAX_READ_SIZE
#define MAX_READ_SIZE 64
#endif

static inline size_t min_size(size_t x, size_t y) { return (x < y) ? x : y; }

static inline ssize_t pseudo_read(int fd, char *buffer, size_t nbytes)
{
    return read(fd, buffer, min_size(MAX_READ_SIZE, nbytes));
}

static inline ssize_t pseudo_write(int fd, const char *buffer, size_t nbytes)
{
    return write(fd, buffer, min_size(MAX_READ_SIZE, nbytes));
}

#undef read
#undef write
#define read(fd, buffer, nbytes) pseudo_read(fd, buffer, nbytes)
#define write(fd, buffer, nbytes) pseudo_write(fd, buffer, nbytes)

#endif

ssize_t multi_read(int fd, char *buffer, size_t nbytes)
{
    ssize_t nb = 0;
    size_t nleft = nbytes;
    ssize_t tbytes = 0;
    while (nleft > 0 && (nb = read(fd, buffer, nleft)) > 0)
    {
        tbytes += nb;
        buffer += nb;
        nleft  -= nb;
    }
    if (tbytes == 0)
        tbytes = nb;
    return tbytes;
}

ssize_t multi_write(int fd, const char *buffer, size_t nbytes)
{
    ssize_t nb = 0;
    size_t nleft = nbytes;
    ssize_t tbytes = 0;
    while (nleft > 0 && (nb = write(fd, buffer, nleft)) > 0)
    {
        tbytes += nb;
        buffer += nb;
        nleft  -= nb;
    }
    if (tbytes == 0)
        tbytes = nb;
    return tbytes;
}

#ifdef TEST

#include "stderr.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
    if (argc != 0)
        err_setarg0(argv[0]);

    char buffer[4096];
    ssize_t ibytes;

    while ((ibytes = multi_read(0, buffer, sizeof(buffer))) > 0)
    {
        ssize_t obytes;
        if ((obytes = multi_write(1, buffer, ibytes)) != ibytes)
            err_syserr("failed to write %lld bytes - only wrote %lld bytes\n",
                       (long long)ibytes, (long long)obytes);
    }
    if (ibytes < 0)
        err_syserr("I/O error reading standard input: ");

    return 0;
}
#endif

通过测试工具,您可以测试从标准输入读取的代码并写入标准输出。您可以通过(例如)编译命令行选项-DMAX_WRITE_SIZE=132-DMAX_READ_SIZE=103配置读取的数据量。您需要在小于(a)4096字节和(b)小于最大读写大小的文件上以及在大于4096字节的文件上进行测试。如果您有足够的动力,则可以升级pseudo_read()pseudo_write()函数以准随机地生成错误,以查看代码如何处理此类错误。