-2

Here's my sender side code

void send_data(int port, int coords[4]){

    struct sockaddr_in si_me, si_other;
    int s, i, slen = sizeof(si_other), recv_len;
    char buf[BUFLEN];

    //create a UDP socket
    if((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
        err_print("socket");
    }

    //zero out the structure
    memset((char*)&si_me, 0, sizeof(si_me));

    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(port);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);

    //bind socket to the port
    if(bind(s, (struct sockaddr *)&si_me, sizeof(si_me) ) == -1){
        err_print("bind");
    }
    int size = sizeof(coords);
    printf("Size: %d\n", size);
    //Keep listening for data
    while(1){
        printf("Waiting for Data\n");
        fflush(stdout);

        memset(buf, 0, BUFLEN);
        //try to receive some data, this is a blocking call
        if((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr*) &si_other, &slen)) == -1){
            err_print("recvfrom()");
        }

        //print details of the client/peer and the data received
        printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
        printf("%s\n", buf);

        if(!strcmp(buf, "coords")) {

            printf("Sending Coordinates: \n");
           //now reply the client with the same data
            int siz = sendto(s, coords, sizeof(coords), 0, (struct sockaddr*) &si_other, slen); 
            if(siz == -1){
                err_print("sendto()");
            }
            printf("Siz: %d\n", siz);

            }

            break;
        }

    }

    close(s);
}

The value returned from sendto is 8 which is the correct size of the int array but at the receiver side recvfrom returns 0 although the array receives the first two integer elements and the rest is garbage values when I print the array. Here's the receiver side code:

void get_data(int port, int coords[]){

    struct sockaddr_in si_other;

    int s, i; 
    char message[BUFLEN];

    if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){
        err_print("socket");
    }

    memset((char*)&si_other, 0, sizeof(si_other));
    si_other.sin_family = AF_INET;

    si_other.sin_port = htons(port);
    si_other.sin_addr.s_addr = inet_addr(SERVER);

    if(inet_aton(SERVER, &si_other.sin_addr) == 0){
        fprintf(stderr, "inet_aton() failed\n");
        exit(1);
    }

    socklen_t slen = sizeof(si_other);


    int size = sizeof(coords);
    printf("Size: %d\n", size);
    int siz = 0;
    while(1)
    {
        printf("Enter message : ");
        strcpy(message, "coords");

        //send the message
        if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1)
        {
            err_print("sendto()");
        }

        //try to receive some data, this is a blocking call

        if (siz = (recvfrom(s, coords, 8, 0, (struct sockaddr *) &si_other, &slen)) == -1)
        {
            err_print("recvfrom()");
        }
        printf("Siz: %d\n", siz);

        break;
    }

    for(int j = 0; j<4; j++){
        printf("C: %d\n", coords[j]);
    }



    close(s);    

    return;
}

And the output of coords array is on the receiver side : 1 2 4196592 0 Now, i thought perhaps, the whole array wasnt getting sent, but the size values returned by sendto is 8 and that of recvfrom is 0 even if it gets the first two elements right. Also, do note that on compilation, I get warning for sizeof: ‘sizeof’ on array function parameter ‘coords’ will return size of ‘int *’

What could be wrong here and what's the right way to send the array? And if possible, could a double array too be sent?

SierraOscar
  • 17,507
  • 6
  • 40
  • 68
Sera_Vinicit
  • 149
  • 3
  • 14
  • Are you setting `slen = sizeof(si_other)` before calling `recvfrom()`? – keithmo Dec 27 '15 at 14:05
  • 1
    Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – too honest for this site Dec 27 '15 at 14:09
  • 1
    If `sizeof(coords)` is `8` on the sending platform that means `sizeof(int)` `2`, i.e. 16 bits. That's only common in small embedded platforms these days, on a normal modern PC `sizeof(int)` is usually `4`. If you send and receive on different platforms you should be using [fixed-width integers](http://en.cppreference.com/w/c/types/integer) to make sure both sending and receiving side have the same size. Also be careful about [endianness](https://en.wikipedia.org/wiki/Endianness) issues. – Some programmer dude Dec 27 '15 at 14:11
  • 1
    You are also misplacing the parenthesis on the receiving side, instead of doing `siz = (recvfrom(...)) == -1` you should do `(siz = recvfrom(...)) == -1` – Some programmer dude Dec 27 '15 at 14:14
  • 2
    In the code you show `coords` is not a parameter, so could not give that error message. You need to post real code that actually shows the problem. [MCVE] – Alan Stokes Dec 27 '15 at 14:17
  • 2
    Or wait, do you mean that `coords` is not actually an array, but a pointer to an `int`? You *do* know that passing an array to a function usually will make it decay to a *pointer* to the first argument, and doing `sizeof` on a pointer returns the size of the *pointer* and not what it points to. This seems to be the culprit behind your problem. – Some programmer dude Dec 27 '15 at 14:18
  • In what universe, since the dawn of the 21st century, is an `int[4]` only eight bytes? – Lightness Races in Orbit Dec 27 '15 at 14:25
  • I checked the sizes of the array. It comes out to be 8. I'll admit it puzzled me too until some other above said about the 16 bit. And, to be clear, the data is being sent onto the same machine i.e 127.0.0.1, so the system doesn't change. And moreover I checked the sizes of the coords array on both the sender and receiver. Both turn out to be 8. – Sera_Vinicit Dec 27 '15 at 14:37

1 Answers1

2

The clue here is the claim in the question is that sizeof(coords), a 4-element int array, results in 8.

This would only be the case, of course, if on this implementation sizeof(int) is 2. I suppose 16-bit platforms are not entirely unheard of these days, especially in embedded space. But then afterwards, a claim is made that printing an int also results in 4196592, which cannot be the case with a two-byte int, of course.

The only explanation is that the example given here leaves out key information. The code that calls sendfrom() does not access the coords array directly. Most likely .the coords array gets passed as a parameter to this function. Which, of course, turns it into an int *, with its sizeof being 8, resulting in just the first two four-byte int values being send across the socket. This is also an explanation of the compiler warning.

Who knows what happens on the receive side.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Yes. I've passed coords as a parameter. It could be a problem, but that doesn't explain why recvfrom returns 0. – Sera_Vinicit Dec 27 '15 at 14:34
  • Even if you send the right amount of data, you *must* read from a socket in a loop until you have read all the data you want. You are *not* guaranteed to get all the data in a single call to recvfrom. – Martin Bonner supports Monica Dec 27 '15 at 14:37
  • Yes. I agree. But recvfrom returns value 0 and not even 2 or 4, even if it has received two elements. I had also thought of a loop, but how can the size be zero even if it received two elements. – Sera_Vinicit Dec 27 '15 at 14:40
  • I used a locally defined array instead of the passed array and that has made all the difference. Even size is coming as the normal 16. Thanks. Although if it could be explained why sizeof(int*) for an array is 8 and not 16? – Sera_Vinicit Dec 27 '15 at 14:54
  • 2
    @MartinBonner, there are no partial reads with UDP, which is a datagram-oriented protocol: http://stackoverflow.com/questions/13317532 – Emile Cormier Dec 27 '15 at 14:57
  • @Sera_Vinicit, `sizeof(int*)` is 8 because a pointer is simply a memory address and you are (presumably) on a 64-bit platform. 64bits / (8 bits / byte) = 8 bytes. – Emile Cormier Dec 27 '15 at 15:07
  • @EmileCormier: Oooh! It's such a common mistake with TCP (particularly as it usually works), that I hadn't realized UDP was different. Thanks for the correction. – Martin Bonner supports Monica Dec 27 '15 at 15:55