0

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);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
BerLin Dz
  • 1
  • 1
  • 1
    If you're having a problem with a particular piece of code, show the code (sender and receiver) along with input, expected output, and actual output. – dbush May 18 '22 at 14:46
  • try sending in fixed size blocks with a length value sent first. – john elemans May 18 '22 at 14:50
  • Sender : pic = (int*) malloc(230400*sizeof(int)) ; write(..,pic,230400*4) ; receiver : recv(..,received_pic,921600,0); – BerLin Dz May 18 '22 at 14:50
  • 2
    you'll need to loop on `recv`, and receive/reassemble/process your data in chunks. This is always true for TCP since it's a byte stream, you can't be sure how the sender will packet-ize the data. Edit your question and post some code if you want help with something specific. There are numerous TCP client/server examples in C online. – yano May 18 '22 at 14:51
  • 1
    Please do not post code in the comments. Edit your question and put it there as formatted text. – yano May 18 '22 at 14:53
  • the problem how i can loop recv() to have the data stored in array of integers ? – BerLin Dz May 18 '22 at 14:55
  • 1
    Does this answer your question? [C socket: recv and send all data](https://stackoverflow.com/questions/13479760/c-socket-recv-and-send-all-data) – G.M. May 18 '22 at 14:57
  • the solution proposed here is for a buffer of type char , i need a solution for array of integers – BerLin Dz May 18 '22 at 15:09
  • `recv` does not know anything about integers, it only knows about bytes. It is possible to receive a non-integral number of integers. – Ian Abbott May 18 '22 at 15:18
  • 1
    @BerLinDz `recv()` takes a `char*` to a memory buffer. It doesn't care what kind of data is written to that buffer. You can use an `int[]` array for the buffer, if you want. – Remy Lebeau May 18 '22 at 20:28

2 Answers2

1

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...
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • please, there is no method to concatenate the received data in array of integers ? – BerLin Dz May 18 '22 at 21:31
  • i need a method to loop the function recv() and concatenate the received data in array of integers – BerLin Dz May 18 '22 at 21:32
  • @BerLinDz The example I gave you does exactly that. Did you even try it? If you know how many integers you are expecting, allocate that array up front, and then pass it into `recv_all()` and it will read the entire array in one go, as it continues writing new bytes received into the array until it has been filled up in full. To better augment this, you can also use `send_all()`/`recv_all()` to send/receive the *number* of integers in the array before then sending/receiving the array itself – Remy Lebeau May 18 '22 at 21:54
  • @BerLinDz eg: `int32_t count = ...; int size = sizeof(int32_t) * count; int32_t *nums = malloc(size); ... send_all(..., &count, sizeof(count)); send_all(..., nums, size);` ... `int32_t count; recv_all(..., &count, sizeof(count)); int size = sizeof(int32_t) * count; int *nums = malloc(size); recv_all(..., nums, size); ...` – Remy Lebeau May 18 '22 at 21:59
0

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;
}
malkaroee
  • 187
  • 1
  • 6