Home > Software engineering >  Using htons() in my code puts all zeros in the buffer and I don't understand why
Using htons() in my code puts all zeros in the buffer and I don't understand why

Time:02-02

I need to use htons() in my code to convert the little-endian ordered short to a network (big-endian) byte order. I have this code:

int PacketInHandshake::serialize(SOCKET connectSocket, BYTE* outBuffer, ULONG outBufferLength) {
    memset(outBuffer, 0, outBufferLength);
    const int sizeOfShort = sizeof(u_short);
    u_short userNameLength = (u_short)strlen(userName);
    u_short osVersionLength = (u_short)strlen(osVersion);
    int dataLength = 1   (sizeOfShort * 2)   userNameLength   osVersionLength;
    outBuffer[0] = id;
    outBuffer[1] = htons(userNameLength);// htons() here
    printf("u_short byte 1: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[1]));
    printf("u_short byte 2: %c%c%c%c%c%c%c%c\n", BYTE_TO_BINARY(outBuffer[2]));
    for (int i = 0; i < userNameLength; i  ) {
        outBuffer[1   sizeOfShort   i] = userName[i];
    }
    outBuffer[1   sizeOfShort   userNameLength] = htons(osVersionLength);// and here
    for (int i = 0; i < osVersionLength; i  ) {
        outBuffer[1   (sizeOfShort * 2)   userNameLength   i] = osVersion[i];
    }
    int result;
    result = send(connectSocket, (char*)outBuffer, dataLength, 0);
    if (result == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
    }
    printf("PacketInHandshake sent: %ld bytes\n", result);
    return result;
}

Which results in a packet like this to be sent:

enter image description here

As you see, the length indication bytes where htons() is used are all zeros, where they should be 00 07 and 00 16 respectively.

And this is the console output:

u_short byte 1: 00000000
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes

If I remove the htons() and just put the u_shorts in the buffer as they are, everything is as expected, little-endian ordered:

enter image description here

u_short byte 1: 00000111
u_short byte 2: 00000000
PacketInHandshake sent: 34 bytes

So what am I doing wrong?

CodePudding user response:

htons converts integers. This is how I used to do this.

    *(int16_t *)(&outBuffer[1]) = htons(userNameLength);

Note that this won't work on all systems because of alignment. This wasn't a problem on any system where I used to write it, but it is on some modern systems (but not x86 or x64).

Now I write (casts suppress compiler warnings):

    outbuffer[1] = (unsigned char)(userNameLength >> 8);
    outbuffer[2] = (unsigned char)userNameLength;

I now use the second because there isn't an htonq. Alignment problems don't come up for me because I design my buffers around the problem, but you did not.

  •  Tags:  
  • Related