arrays - 如何在 C 中使用 TCP 套接字接收 integers 的长数组?

如何使用 TCP sockets 发送和接收一长串 integers?

在短数组的情况下,可以使用函数recv(.., 4*size of array) 接收一次,但是当数组的大小太长时,我无法正确接收数据。

int main(void)
{
    int listenfd = 0, connfd = 0;
    int i,j,x;
    int         fd;
    unsigned int    *pic;

    struct sockaddr_in serv_addr; 
    char *recvBuff;
    clock_t t;


    //Allocate memory for a 24-bit 640x480 rgb image
    pic = (int*)malloc(10*sizeof(int));
    recvBuff = (char*)malloc(1*sizeof(char));

    for(i = 0; i < 10 ; i++){
        pic[i] = 20;    
    } 



    //Create the TCP socket
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    memset(&serv_addr, '0', sizeof(serv_addr));
    memset(pic, '0', sizeof(pic)); 

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(7); // la valeur du port 

    bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); 

    listen(listenfd, 10); 
    //fprintf(stdout,"End Creating Socket4\n");
    connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); 

    while(1)
    {
                
        recv(connfd,recvBuff, sizeof(char),MSG_WAITALL);
        //printf("BUFF: %s\n",recvBuff);
        //Wait for client request 
        if(strcmp(recvBuff,"A")){
            printf("Error in input\n");
        }else
            write(connfd, pic, 921600); 
    
    }
    close(connfd);
}

回答1

在短数组的情况下,可以使用函数recv(.., 4*size of array)一次接收

这是不能保证的。任何对 recv() 的调用都可以返回比请求更少的字节,甚至只有 1 个字节。因此,您总是需要在循环中调用 recv() ,直到您实际收到与您期望的一样多的字节,例如:

ssize_t recv_all(int skt, void *buf, size_t bufsize)
{
    char *ptr = (char*) buf;
    while (bufsize > 0)
    {
        ssize_t recvd = recv(skt, ptr, bufsize, 0);
        if (recvd <= 0) return recvd;
        ptr += recvd;
        bufsize -= recvd;
    }
    return 1;
}

然后你可以这样称呼它:

int32_t *arr = (int32_t*) malloc(sizeof(int32_t) * count);
...
if (recv_all(..., arr, sizeof(int32_t) * count) <= 0)
{
    // error, or peer disconnected...
}
else
{
    // use arr as needed...
}

您也应该为 send() 做同样的事情,例如:

ssize_t send_all(int skt, const void *buf, size_t bufsize)
{
    const char *ptr = (const char*) buf;
    while (bufsize > 0)
    {
        ssize_t sent = send(skt, ptr, bufsize, 0);
        if (sent < 0) return sent;
        ptr += sent;
        bufsize -= sent;
    }
    return 0;
}
int32_t *arr = (int32_t*) malloc(sizeof(int32_t) * count);
...
if (send_all(..., arr, sizeof(int32_t) * count) < 0)
{
    // error...
}
else
{
    // arr sent in full...
}

回答2

首先,值得注意的是 recv() 根本不关心它接收到的数据类型,只关心它的大小。

所以你所需要的只是一个在循环中调用 recv() 直到它接收到所有请求的数据的函数

// Returns the number of bytes read, or -1 in the case of an error
ssize_t recv_all(const int sock, void * const buf, const size_t n)
{
    ssize_t len = 0;
    ssize_t total_read = 0;

    while (n > (size_t)total_read)
    {
        len = recv(sock, (char *)buf + total_read, n - total_read, MSG_WAITALL);

        switch (len)
        {
        case -1:
            return -1;

        case 0:
            break;

        default:
            total_read += len;
        }
    }

    return total_read;
}

相似文章