ddingz 2021. 12. 26. 19:55

바이트 순서(byte order)에는 호스트 바이트 순서와 네트워크 바이트 순서 두 가지가 있다.
호스트 바이트 순서는 컴퓨터가 내부 메모리에 숫자를 저장하는 순서를 말하는데, 이것은 CPU의 종류에 따라 다르다.
네트워크 바이트 순서는 포트번호나 IP 주소와 같은 정보를 바이트 단위로 네트워크로 전송하는 순서를 말한다.
바이트 순서를 바꾸는 함수에는 변환할 바이트 길이가 2 바이트인 경우 또는 4 바이트인 경우에 따라 다음과 같이 두 가지 종류가 있다.

  • Unsigned short interger 변환 (2 바이트 크기)
    • htons(): host-to-network 바이트 변환
    • ntohs(): network-to-host 바이트 변환
  • Unsigned long interger 변환 (4 바이트 크기)
    • htonl(): host-to-network 바이트 변환
    • ntohl(): network-to-host 바이트 변환

byte_order.c

현재 사용 중인 컴퓨터의 호스트 바이트 순서가 네트워크 바이트 순서와 같은지를 알아보는 테스트 프로그램이다.

pmyservent = getservbyname("echo", "udp");

getservbyname()은 시스템이 현재 지원하는 특정 응용 프로그램의 정보를 알아내는 함수로 서비스 이름과 프로토콜을 인자로 주어 호출하면 서비스와 관련된 각종 정보를 포함하고 있는 servent라는 구조체의 포인터를 리턴한다.

struct servent {
    char *s_name; // 서비스 이름
    char **s_aliases; // 별명 목록
    int s_port; // 포트번호
    char *s_proto; // 사용하는 프로토콜
};

servent 구조체는 네트워크로부터 얻은 정보이므로 그 내용이 네트워크 바이트 순서로 되어 있고 이를 화면에 출력해 보려면 호스트 바이트 순서로 바꾸어야 한다.

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(void) {
    struct servent *servent;

    servent = getservbyname("echo", "udp");

    if (servent == NULL) {
        printf("서비스 정보를 얻을 수 없음.\n\n");
        exit(0);
    }

    printf("UDP 에코 포트번호(네트워크 순서) : %d\n", servent->s_port);
    printf("UDP 에코 포트번호(호스트 순서) : %d\n", ntohs(servent->s_port));

    return 0;
}

실행 결과

인텔 80x86 계열의 CPU를 사용하는 컴퓨터(PC)에서 byte_order.c를 실행한 결과가 아래와 같았으며 호스트 바이트 순서가 네트워크 바이트 순서와 다르다는 것을 알 수 있다.

썬 마이크로시스템즈의 Sparc 시스템에서 byte_order.c를 실행하면 결과가 아래와 같이 되며 따라서 이 경우에는 호스트 바이트 순서가 네트워크 바이트 순서와 같다는 것을 알 수 있다.

./byte_order
UDP 에코 포트번호(네트워크 순서) : 7
UDP 에코 포트번호(호스트 순서) : 7