Search code examples
cwindowssocketsintegerwinsock

Sending integer over windows socket in c


I am attempting to send a integer over the network in C (more specifically, uint32_t bytes). I believe I am sending the data correctly, according to other examples and answers on Stack Overflow; however, when receiving the bytes, I am having trouble casting/converting them to uint32_t. Here is an example of my attempt:

Sender:

    uint32_t num = htonl(100);
    char* converted_num = (char*)#
    send(client_sock, converted_num, sizeof(num), 0);

Receiver:

    char buf[8192];
    recv(socket, buf, 8192, 0);
    uint32_t test = ntohl((uint32_t)&buf);
    printf("%d\n", (int)test);

The receiver outputs a large integer 1755042816 and not the correct integer value "100". What am I doing wrong?


Solution

  • You're casting a pointer to an integer which won't work. *(uint32_t*)&buf might work if you're lucky, but it's undefined-behavior C due to a strict aliasing violation.

    To be correct, you should first memcpy to an uin32_t and then apply nthol to that.

    static inline uint32_t ntohl_ch(char const *X)
    {
        uint32_t x; memcpy(&x,X,sizeof(x));
        return ntohl(x);
    }
    
    //...
        uint32_t test = ntohl_ch(&buf[0]);
    //...
    

    Strict aliasing allows you to treat any object as an array of char (or signed char or unsigned char). The reverse is not true. Imagining an uint32_t in an array of char is not allowed and you must use memcpy.

    Optimizing compilers will notice you're memcpy'ing just an uint32_t and elide a full memcpy call (in favor of a direct mov to register or a direct application of a an assembly instruction on the original memory).