BerLin Dz
BerLin Dz

Reputation: 1

How to receive long array of integers with TCP socket in C?

How can I send and receive a long array of integers using TCP sockets?

In the case of short array, the reception is possible using the function recv(.., 4*size of array) one time, however when the size of array is too long, I can't receive data correctly.

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);
}

Upvotes: 0

Views: 427

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595827

In the case of short array, the reception is possible using the function recv(.., 4*size of array) one time

That is not guaranteed. Any call to recv() can return fewer bytes than requested, even as few as just 1 byte. So you always need to call recv() in a loop until you have actually received as many bytes as are you expecting, eg:

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;
}

And then you can call it like this:

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...
}

You should do the same thing for send() too, eg:

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...
}

Upvotes: 1

malkaroee
malkaroee

Reputation: 187

First of all, it's worth noting that recv() doesn't care at all about the type of data it receives, only about its size.

So all you need is a function that calls recv() in a loop until it receives all of the requested data

// 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;
}

Upvotes: 0

Related Questions