[Network Basic] Byte Order Function

바이트 순서 관련 함수

네트워크 프로그래밍을 위해 추가로 신경 써야 하는 것이 바로 데이터의 바이트 순서이다.
 바이트 순서는 리틀 엔디언과 빅 엔디언의 두 가지가 있다. Intel 의 경우 리틀 엔디언을 사용하고 모토로라 등은 빅 엔디언을 사용하는데 이때 각각의 엔디언에 맞게 전송해주어야 한다.

종류 0x12345678의 표현
리틀 엔디언(Little Endian) 78 56 34 12
빅 엔디언(Big Endian) 12 34 56 78

대부분의 호스트 시스템은 리틀 엔디언을 사용하고 대부분의 네트워크 장비는 빅 엔디언 방식을 사용하기 때문에 네트워크 프로그래밍을 할 때에는 이를 맞춰 변환 해주어야 한다.

이에 C 언어는 효율적으로 바이트 순서를 변환할 수 있다록 지원한다.
이번 포스트에서는 그 함수들을 알아보자.

header : #include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong)
         > 4바이트 값의 호스트 바이트 순서를 네트워크 바이트 순서로 변환한다.

uint32_t htons(uint32_t hostshort)
         > 2바이트 값의 호스트 바이트 순서를 네트워크 바이트 순서로 변환한다.

uint32_t ntohl(uint32_t netlong)
         > 4바이트 값의 네트워크 바이트 순서를 호스트 바이트 순서로 변환한다.

uint32_t ntohs(uint32_t netshort)
         > 2바이트 값의 네트워크 바이트 순서를 호스트 바이트 순서로 변환한다.


네트워크 바이트 순서와 호스트 바이트 순서 비교 예제

#include <stdio.h>
#include <arpa/inet.h>

void print2hex(const char *msg, void *p, size_t len);

int main(void)
{
    int a = 0x12345678;
    int b = htonl(0x12345678);
    int c = htonl(b);

    print2hex("a", &a, sizeof(a));
    print2hex("b", &b, sizeof(b));
    print2hex("c", &c, sizeof(c));
}

void print2hex(const char *msg, void *p, size_t len){
    size_t i;

    printf("%s :\n",msg);
    for(i=0;i<len;i++){
        printf("[%p]%x ",((char*)p+i), *((char*)p+i));
    }
    printf("\n");
}

출력

a :
[0x7ffcaa5c21e4]78 [0x7ffcaa5c21e5]56 [0x7ffcaa5c21e6]34 [0x7ffcaa5c21e7]12 
b :
[0x7ffcaa5c21e8]12 [0x7ffcaa5c21e9]34 [0x7ffcaa5c21ea]56 [0x7ffcaa5c21eb]78 
c :
[0x7ffcaa5c21ec]78 [0x7ffcaa5c21ed]56 [0x7ffcaa5c21ee]34 [0x7ffcaa5c21ef]12

위 출력에서 a는 호스트에서 저장될 때 리틀 엔디언으로 저장되는 것을 보여준다.
b와 같은 경우는 htonl()함수를 동해 리틀 엔디언을 빅 엔디언으로 변환 한 것을 보여준다.
c와 같은 경우는 htonl()함수를 다시 사용해 빅 엔디언을 리틀 엔디언으로 변환 한 것 이다.

위와 같이 htonl()과 ntohl()을 크게 구분하지 않아도 되지만,
프로그래밍 함에 있어서 버그를 발생 시키지 않도록 구분해서 사용하는 것이 좋다.


네트워크 주소와 관련된 함수

header : #include <sys/socket.h>
              #include <netinet/in.h>
              #include <arpa/inet.h>

in_addr_t inet_addr(const char *cp)
         > 일반적으로 표기하는 IP 주소 형태(0.0.0.0)를 4 Byte의 네트워크 바이트 순서로 변환하는 함수

char *inet_ntoa(strcut in_addr in)
         > 4 Byte의 네트워크 바이트 순서를 일반적으로 표기하는 IP 주소 형태(0.0.0.0)로 변환하는 함수


inet_addr 및 inet_ntoa 사용 예제

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void print2hex(void *p, size_t len);

int main(void)
{
    struct in_addr addr;

    addr.s_addr = inet_addr("127.0.0.1");

    printf("inet_addr : %08x\n", addr.s_addr);
    print2hex(&addr.s_addr, sizeof(addr.s_addr));
    printf("inet_ntoa : %s\n", inet_ntoa(addr));

    return 0;
}


void print2hex(void *p, size_t len){
    size_t i;

    for(i=0;i<len;i++){
        printf("[%p]%x ",((char*)p+i),*((char *)p+i));
    }
    printf("\n");
}

출력

inet_addr : 0100007f
[0x7ffe0f730c30]7f [0x7ffe0f730c31]0 [0x7ffe0f730c32]0 [0x7ffe0f730c33]1 
inet_ntoa : 127.0.0.1
Press <RETURN> to close this window...

 

글의 문제가 있다면 댓글을 달아 주세요.

This site uses Akismet to reduce spam. Learn how your comment data is processed.