[태그:] <span>htonl 함수</span>

바이트 정렬은 2 바이트 이상의 데이터를 메모리에 표현할 때 높은 주소부터 시작할 지 낮은 주소부터 시작할 지를 결정하는 것을 말합니다. 시스템에 따라 바이트 정렬 방식은 다른데 Sparc나 Motorola는 높은 주소부터 시작하는 big endian 바이트 정렬 방식을 사용하며 Intel 호환 시스템은 little endian 바이트 정렬 방식을 채택하고 있습니다.

이처럼 네트워크 통신의 호스트에 따라 정렬 방식이 다를 수 있어서 네트워크 통신 표준을 정하였는데 이를 네트워크 바이트 정렬이라 부르며 big endian 방식을 채택하였습니다.

“네트워크 바이트 정렬은 big endian 방식”

그리고 윈속에서는 호스트 데이터를 네트워크 바이트 정렬 방식의 데이터로 바꾸거나 네트워크 데이터를 호스트 바이트 정렬 방식의 데이터로 바꾸는 함수를 제공하고 있습니다.

만약 이 함수를 호출했을 때 내용의 변화가 없으면 호스트 바이트 정렬 방식과 네트워크 정렬 방식은 같은 방식을 사용하는 것입니다. 반대로 변화가 있으면 서로 다른 방식을 사용하는 것입니다.

호스트 바이트 정렬 방식의 4바이트 데이터를 네트워크 바이트 정렬 방식으로 변환
u_long htonl(u_long hostlong); 
호스트 바이트 정렬 방식의 2바이트 데이터를 네트워크 바이트 정렬 방식으로 변환
u_short htons(u_short hostshort);
네트워크 바이트 정렬 방식의 4바이트 데이터를 호스트 바이트 정렬 방식으로 변환
u_long ntohl(u_long netlong);
네트워크 바이트 정렬 방식의 2바이트 데이터를 호스트 바이트 정렬 방식으로 변환
u_short ntohs(u_short netshort);
//바이트 정렬
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib,"ws2_32")
int main()
{
    WSADATA wsadata;
    WSAStartup(MAKEWORD(2,2),&wsadata);

    unsigned int idata = 0x12345678;
    unsigned short sdata = 0x1234;

    //4바이트 정수를 네트워크 바이트 정렬로 변환 후 출력
    printf("host:%#x network:%#x\n",idata, htonl(idata));
    //2바이트 정수를 네트워크 바이트 정렬로 변환 후 출력
    printf("host:%#x network:%#x\n",sdata, htons(sdata));
    
    WSACleanup();
    return 0;
}

실행 결과

host:0x12345678 network:0x56781234
host:0x1234 network:0x3412

htonl 함수를 호출했을 때 원래 값이 바뀌었다면 호스트 바이트 정렬 방식이 little endian 방식이기 때문입니다. 이 때 ntohl 함수를 호출하면 htonl과 마찬가지로 동작할 것입니다. 그럼에도 불구하고 논리적인 코드를 작성할 때 왜 해당 함수를 사용했는지 이해할 수 쉽게 작성하라고 제공하고 있습니다.

TCP/IP 소켓 프로그래밍 with 윈도우즈