주소 체계와 데이터 정렬 1
1. Internet Address |
IP 주소란, 인터넷상에 존재하는 호스트들을 구분하기 위한 32비트 주소 체계를 의미한다.
일반적으로 점이 찍힌 십진수 표현 방식(Dotted-decimal Notation)을 사용해서 IP 주소를 표현하는데, 점에 의해 구분되는 각각의 십진수 값은 1바이트로 표현된다. 따라서 총 4바이트를 사용하게 된다.
4바이트 IP 주소는 네트워크 주소와 호스트 주소로 나뉘며, 주소의 형태에 따라 A,B,C,D,E 클래스로 분류할 수 있다.
2. Port란 무엇인가? |
32비트 IP 주소로는 네트워크상에 존재하는 호스트를 구분하게 되고, 16비트 Port정보로는 호스트 내에서 실행되고 있는 프로그램을 구분하게 된다. 이것은 물리적인 개념의 할당이 아니라, 동일 호스트 내에서의 논리적인 할당일 뿐이다.
Port를 할당 받은 프로세스
Port는 2바이트로 표현되므로 가질 수 있는 값의 범위가 0에서 65535까지다. 그러나 0부터 1023번 까지는 '잘 알려진 Port(well-known ports)' 라고 해서, 예약되어 있는 Port이므로 사용이 제한된다. 사용할 수 없는 것은 아니나 사용되는 용도를 약속해 놓았다는 것이다. 또한 Port는 중복될 수 업승나, TCP 소켓과 UDP소켓은 Port를 서로 공유하지 않으므로 중복되어도 상관없다.
즉 TCP 소켓을 생성할 떄 9000 Port를 사용했다면, 다른 TCP 소켓은 9000 Port를 사용할 수 없지만, UDP소켓은 9000 Port를 사용할 수 있다.
결론적으로 데이터 전송의 최종 목적지는 호스트가 아니라 실행 중에 있는 프로그램이다. 따라서 데이터를 보내기 위해서는 데이터 패킷 내에 IP 주소 정보뿐만 아니라 Port 정보도 함께 포함을 시켜야 한다.
3. 주소 정보의 표현 |
모든 프로토콜은 자신만의 고유한 주소 포맷이 있다. 예를 들어 IPv4에서는 32비트 주소 체계를 사용하지만, IPv6에서는 128비트 주소 체계를 사용한다. 그러므로 프로토콜에 따라 주소 정보를 나타내닌 데이터 타입이 독립적으로 존재한다.
1. IPv4의 주소 체계를 나타내는 구조체
struct sockaddr_in { sa_family_t sin_family; /* 주소 체계(address family) */ uint16_t sin_port; /* 16비트 TCP / UDP Port */ struct in_addr sin_addr; /* 32비트 IPv4 주소 */ char sin_zero[8]; /* 사용되지 않음 */ };
struct in_addr { uint32_t s_addr; /* 32비트 IPv4 인터넷 주소 */ };
이러한 데이터 타입들은 POSIX에서 그 근거를 찾을 수 있다. POSIX(Portable Operation System Interface)란 유닉스 계열의 운영 체제를 위해 표준화 해 놓은 인터페이스(API)다.
Data type |
Description |
Header |
int8_t uint8_t int16_t uint16_t int32_t uint32_t |
signed 8-bit int unsigned 8-bit int (unsigend char) signed 16-bit int unsigned 16-bit int (unsigned short) signed 32-bit int unsigned 32-bit int (unsigned long) |
<sys/types/h> |
sa_family_t socklen_t |
address family length of struct |
<sys/socket.h> |
2. sockaddr_in 구조체 정보
■ sin_family : 사용되는 주소 체계에 대한 정보를 대입한다.
주소체계(Address Family) |
정의 |
AF_INET |
IPv4 인터넷 프로토콜 |
AF_INET6 | IPv6 인터넷 프로토콜 |
AF_LOCAL | Local 통신을 위한 UNIX 프로토콜 |
■ sin_port : 16비트 Port 정보를 대입해 준다. 네트워크 바이트 순서로 대입해야 한다.
■ sin_addr : 32비트 IP 주소 정보를 대입해 준다. 네트워크 바이트 순서로 대입해야 한다.
■ sin_zero : 특별한 의미 없이 단순한 채워주기 위한 목적으로 사용되는 구조체 멤버이다.
4. 네트워크 바이트 순서 |
바이트 순서라는 것은 시스템이 내부적으로 데이터를 표현하는 방법을 의미한다. 모든 시스템의 내부적인 데이터 표현방식이 같은 것은 아니다.
크게 두 가지 방법으로 나뉘는데, 하나는 Big-Endian 방식이고 또 하나는 Little-Endian 방식이다. 이 두가지 방법을 이용하여 0x12345678이라는 32비트 값을 표현해 보자.
1. 바이트 순서(Byte Order)
■ Big-Endian 표현 방식 : 0x12345678
상위 바이트의 값이 메모리상에 먼저 표시되는 방법이다.
■ Little-Endian 표현 방식 : 0x78563412
하위 바이트의 값이 메모리상에 먼저 표시되는 방법이다.
시스템이 내부적으로 데이터를 처리하는데 있어서 Big-Endian 방식을 쓰느냐, Little-Endian 방식을 쓰느냐는 시스템의 CPU에 따라 달라진다. 이를 '호스트 바이트 순서(Host Byte Order)'라고 하는데 문제는 호스트 바이트 순서가 일정치 않다는 것이다. Motorola 68000계열이 주소 Big-Endian 방식을 쓰고, 가장 많이 사용되는 Intel x86 계열은 Little-Endian 방식을 쓰고 있다. 따라서 만약에 서로 다른 CPU를 장착하고 있는 호스트들이 데이터를 주고 받을 경우 문제가 발생할 수 있다.
이러한 문제점 떄문에 네트워크를 통해 데이터를 전송할 떄는 통일된 방식을 이용해 데이터를 전송하기로 약속을 하였는데, 이것이 바로 '네트워크 바이트 순서(Network Byte Order)'이다. 네트워크 바이트 순서는 Big-Endian 방식만을 사용하기로 약속되어 있다.
2. 바이트 순서 변환(Endian Conversions)
'h' : host byte order |
'n' : network byte order |
's' : short (16bit) |
'l' : long (32bit) |
● unsigned short htons(unsigned short);
● unsigned short ntohs(unsigned short);
● unsigned long htonl(unsigned long);
● unsigned long ntohl(unsigned long);