sockaddr_in 구조체 변수에 값을 대입할 경우에는 네트워크 바이트 순서(Network-byte Ordering)로 값을 변경한 다음에 대입해야 한다. 네트워크 바이트 순서에 대해 이야기 하기전에 바이트 순서의 의미부터 시작해 보자. 바이트 순서라는 것은 시스템이 내부적으로 데이터를 표현하는 방법을 의미한다. 여기서 데이터 표현방식은 모든 시스템이 같은것이 아니다. 크게 두 가지 방법으로 나뉘는데, 하나는 Big-Endian 방식이고 또 하나는 Little-Endian 방식이다.
바이트 순서(Byte Order)
Big-Endian은 상위 바이트의 값 이 메모리상에 먼저(번지수가 작은 위치에) 저장되는 순서이며, Little-Endian은 하위 바이트의 값이 메모리상에 먼저(번지수가 작은 위치에) 저장되는 순서이다. 즉, 두 방식은 표현 방법이 반대이다.
예를 들면, 빅 엔디안 컴퓨터에서는 16진수 "4F52"를 저장공간에 "4F52"라고 저장할 것이다 (만약 4F가 1000번지에 저장되었다면, 52는 1001번지에 저장될 것이다). 반면에, 리틀 엔디안 시스템에서 이것은 "524F"와 같이 저장될 것이다.
시스템이 내부적으로 데이터를 처리하는데 있어서 Big-Endian 방식을 쓰느냐, Little-Endian을 쓰느냐는 시스템의 CPU에 따라 달라진다. 이를 '호스트 바이트 순서(Host Byte Order)' 라고 하는데 문제는 호스트 바이트 순서가 일정치 않다는 것이다. 따라서 만약 서로 다른 CPU를 장착하고 있는 호스트들이 데이터를 주고 받을 경우 문제가 발생할 수 있다.
만약, 0x1234의 데이터를 전송한다고 가정했을때 Big-Endian 시스템에서의 0x12, 0x34의 조합이 나타내는 값은 Little-Endian 시스템에서의 0x34, 0x12 조합이 나타내는 값과 동일하다(즉 표현되는 순서가 바뀌어야 동일한 값을 나타낸다.) 그러나 Big-Endian 시스템에서 0x12, 0x34의 순서로 데이터를 전송했고, Little-Endian 시스템에서는 보내준 순서로 데이터를 조합했다면 두 호스트 사이에서 주고 받은 데이터는 서로 다른 값으로 해석된다.
이러한 문제점 때문에 네트워크를 통해 데이터를 전송할 때는 통일된 방식을 이용해서 데이터를 전송하기로 약속을 하였는데, 이것이 바로 '네트워크 바이트 순서(Network Byte Order)' 이다. 네트워크 바이트 순서는 Big-Endian 방식만을 사용하기로 약속되어 있다.
따라서 시스템이 Little-Endian 방식을 사용할 경우, 네트워크를 통해 데이터를 전송하기 전에 Big-Endian 방식으로 데이터를 변경해서 보내야만 하고, 받을 때도 Little-Endian 시스템은 전송되어 오는 데이터를 역순으로 조합해야 한다. 또한 sockaddr_in 구조체 안에 존재하는 모든 값들은 '네트워크 바이트 순서'로 채워져야 한다.
바이트 순서 변환(Endian Conversions)
바이트 순서를 Big-Endian 방식으로 변경하기 위해 필요한 함수에 대해 살펴보자.
여기서 htonl이란 h to n 을 의미하고 Host Byte 순서를 Network Byte 순서로 바꾸어 준다는 의미이다. 또한 뒤에 붙는 l은 long, s는 short 타입을 의미한다. 따라서 32비트 데이터를 호스트 바이트 순서에서 네트워크 바이트 순서로 바꿔주는 함수이다.
일반적으로 뒤에 s(short)가 붙은 함수는 s가 2바이트 데이터를 의미하므로 Port 정보의 바이트 순서를 변경하는데 사용하고, l(long)이 붙은 함수는 l이 4바이트를 의미하므로 IP 주소의 바이트 순서를 변경하는데 사용하게 된다.
바이트 순서(Byte Order)
Big-Endian은 상위 바이트의 값 이 메모리상에 먼저(번지수가 작은 위치에) 저장되는 순서이며, Little-Endian은 하위 바이트의 값이 메모리상에 먼저(번지수가 작은 위치에) 저장되는 순서이다. 즉, 두 방식은 표현 방법이 반대이다.
예를 들면, 빅 엔디안 컴퓨터에서는 16진수 "4F52"를 저장공간에 "4F52"라고 저장할 것이다 (만약 4F가 1000번지에 저장되었다면, 52는 1001번지에 저장될 것이다). 반면에, 리틀 엔디안 시스템에서 이것은 "524F"와 같이 저장될 것이다.
시스템이 내부적으로 데이터를 처리하는데 있어서 Big-Endian 방식을 쓰느냐, Little-Endian을 쓰느냐는 시스템의 CPU에 따라 달라진다. 이를 '호스트 바이트 순서(Host Byte Order)' 라고 하는데 문제는 호스트 바이트 순서가 일정치 않다는 것이다. 따라서 만약 서로 다른 CPU를 장착하고 있는 호스트들이 데이터를 주고 받을 경우 문제가 발생할 수 있다.
만약, 0x1234의 데이터를 전송한다고 가정했을때 Big-Endian 시스템에서의 0x12, 0x34의 조합이 나타내는 값은 Little-Endian 시스템에서의 0x34, 0x12 조합이 나타내는 값과 동일하다(즉 표현되는 순서가 바뀌어야 동일한 값을 나타낸다.) 그러나 Big-Endian 시스템에서 0x12, 0x34의 순서로 데이터를 전송했고, Little-Endian 시스템에서는 보내준 순서로 데이터를 조합했다면 두 호스트 사이에서 주고 받은 데이터는 서로 다른 값으로 해석된다.
이러한 문제점 때문에 네트워크를 통해 데이터를 전송할 때는 통일된 방식을 이용해서 데이터를 전송하기로 약속을 하였는데, 이것이 바로 '네트워크 바이트 순서(Network Byte Order)' 이다. 네트워크 바이트 순서는 Big-Endian 방식만을 사용하기로 약속되어 있다.
따라서 시스템이 Little-Endian 방식을 사용할 경우, 네트워크를 통해 데이터를 전송하기 전에 Big-Endian 방식으로 데이터를 변경해서 보내야만 하고, 받을 때도 Little-Endian 시스템은 전송되어 오는 데이터를 역순으로 조합해야 한다. 또한 sockaddr_in 구조체 안에 존재하는 모든 값들은 '네트워크 바이트 순서'로 채워져야 한다.
바이트 순서 변환(Endian Conversions)
바이트 순서를 Big-Endian 방식으로 변경하기 위해 필요한 함수에 대해 살펴보자.
'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);
'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);
여기서 htonl이란 h to n 을 의미하고 Host Byte 순서를 Network Byte 순서로 바꾸어 준다는 의미이다. 또한 뒤에 붙는 l은 long, s는 short 타입을 의미한다. 따라서 32비트 데이터를 호스트 바이트 순서에서 네트워크 바이트 순서로 바꿔주는 함수이다.
일반적으로 뒤에 s(short)가 붙은 함수는 s가 2바이트 데이터를 의미하므로 Port 정보의 바이트 순서를 변경하는데 사용하고, l(long)이 붙은 함수는 l이 4바이트를 의미하므로 IP 주소의 바이트 순서를 변경하는데 사용하게 된다.
'Study > TCP/IP' 카테고리의 다른 글
인터넷 주소 초기화 (3) | 2008.02.16 |
---|---|
인터넷 주소 조작하기 (0) | 2008.02.16 |
주소 정보의 표현 (0) | 2008.02.16 |
Port란, (0) | 2008.02.16 |
Internet Address (0) | 2008.02.16 |