엔디안[Endian]

      단어를 형성하는 2진 바이트에서 저장하는 바이트의 순서를 나타내는 방법.

-네이버 백과사전 펌


나름 백과사전에서 퍼오긴 했지만 너무 어렵다..-_-;;

 Endian은 메모리에 데이터를 배치하는 방법을 말하는 것인데, Endian에는 Little Endian과 Big Endian이 있다. 이 두개의 차이점을 예를 통해서 쉽게 알 수 있다.

Example:
어떤 값이 있다고 하자. 16진수로 0x82D4라는 값이 있다면,
     Little Endian : 0xD482
     Big Endian   : 0x82D4

 두 방식의 차이점은 이거밖에 없다. 단지 네트워크상에서의 표준은 Big Endian을 따른다는 점이다. 아참, 보통 인텔의 Pentium에서는 Little Endian을 쓴다는것! 그래서 네트워크로 데이터를 교환할때는 Little Endian과 Big Endian을 서로 변환해야 할 필요가 생긴다.

그렇다면 [C]에서는 어떻게 변환할 수 있을까?
** 이 곳의 모든 함수는 winsock2.h를 Include해야합니다.
** 필자의 경우에 Host는 Little Endian을 사용한다.
** 왼쪽 함수는 Original함수, 오른쪽함수는 확장함수이다. 확장함수의 이점은 함수가 소켓을 인수로 받기때문에, 소켓이 사용하는 네트워크에 맞게 변환해준다는 이점이 있다. 결과는 동일하다.

htons(Host TO Network Short), WSAHtons

 이 함수는 unsigned short형식의 자료를 호스트에서 사용하는 엔디안에서 네트워크가 사용하는 엔디안(Big Endian)으로 변환해준다. 주로 포트번호 변환에 사용된다.

void main() //htons 버전
{
     unsigned short ex=0x1234;
     printf("Before : 0x%04x \n", ex);
     ex = htons(ex);
     printf("After : 0x%04x \n", ex);    
}

void main() //WSAHtons 버전
{
     WSADATA wsaData;
     WSAStartup(MAKEWORD(2,2), &wsaData);

     SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

     unsigned short before=0x1234, after;
     printf("Before : 0x%04x \n", before);
     WSAHtons(sock, before, &after);
     printf("After : 0x%04x \n", after);    

     closesocket(sock);
     WSACleanup();
}

(결과)
Before : 0x1234
After : 0x3412

ntohs(Network TO Host Short), WSANtohs

 
이 함수는 unsigned short형식의 자료를 네트워크가 사용하는 엔디안(Big Endian)에서 호스트에서 사용하는 엔디안으로 변환해준다. 주로 포트번호 변환에 사용된다.

void main() //ntohs버전
{
     unsigned short ex=0x1234;
     printf("Before : 0x%04x \n", ex);
     ex = ntohs(ex);
     printf("After : 0x%04x \n", ex);    
}

void main() //WSANtohs 버전
{
     WSADATA wsaData;
     WSAStartup(MAKEWORD(2,2), &wsaData);

     SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

     unsigned short before=0x1234, after;
     printf("Before : 0x%04x \n", before);
     WSANtohs(sock, before, &after);
     printf("After : 0x%04x \n", after);    

     closesocket(sock);
     WSACleanup();
}

(결과)
Before : 0x1234
After : 0x3412

htonl(Host TO Network Long), WSAHtonl

 이 함수는 unsigned long형식 또는 DWORD형식의 자료를 호스트에서 사용하는 엔디안에서 네트워크가 사용하는 엔디안(Big Endian)으로 변환해준다. 주로 IP주소 변환에 사용된다.

void main() //htonl버전
{
     unsigned long ex=0x12345678;
     printf("Before : 0x%08x \n", ex);
     ex = ntohl(ex);
     printf("After : 0x%08x \n", ex);    
}

void main() //WSAHtonl 버전
{
     WSADATA wsaData;
     WSAStartup(MAKEWORD(2,2), &wsaData);

     SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

     unsigned long before=0x12345678, after;
     printf("Before : 0x%08x \n", before);
     WSAHtonl(sock, before, &after);
     printf("After : 0x%08x \n", after);    

     closesocket(sock);
     WSACleanup();
}

(결과)
Before : 0x12345678
After : 0x78563412

ntohl(Network TO Host Long), WSANtohl

 
이 함수는 unsigned long형식 또는 DWORD형식의 자료를 네트워크가 사용하는 엔디안(Big Endian)에서 호스트에서 사용하는 엔디안으로 변환해준다. 주로 IP주소 변환에 사용된다.

void main() //ntohl버전
{
     DWORD ex=0x12345678;
     printf("Before : 0x%08x \n", ex);
     ex = ntohl(ex);
     printf("After : 0x%08x \n", ex);    
}

void main() //WSANtohl 버전
{
     WSADATA wsaData;
     WSAStartup(MAKEWORD(2,2), &wsaData);

     SOCKET sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

     DWORD before=0x12345678, after;
     printf("Before : 0x%08x \n", before);
     WSAHtons(sock, before, &after);
     printf("After : 0x%08x \n", after);    

     closesocket(sock);
     WSACleanup();
}

(결과)
Before : 0x12345678
After : 0x78563412


** 참고, 도트 표기법으로된 IP주소를 4바이트 IP주소(IPv4)로 변환하기.

inet_addr

 
IPv4로 변환할때, 결과값은 네트워크 바이트오더에 따릅니다. 즉, inet_addr의 결과를 htonl함수를 사용하여 따로 변환할 필요가 없다는 말이 되겠습니다.

void main()
{
     char MyIP[] = "211.179.80.239";

     printf("IPv4 : 0x%x\n", inet_addr(MyIP));
}

(결과)
IPv4 : 0xef50b3d3          
(결과해석)
결과값인 0xef50b3d3은 바로 해석하면 239.80.179.211이 됩니다. 즉, 네트워크 바이트오더입니다.

inet_ntoa

 inet_addr의 반대기능을 하는 함수. 이것도 네트워크 바이트오더에 따르는 IPv4를 host에서 사용하는 바이트오더로 자동 변환 후 보여주기 때문에 따로 형식변환을 할 필요가 없습니다.

void main()
{
     in_addr MyIP;

     MyIP.S_un.S_addr = 0xef50b3d3;
     printf("IP : %s\n", inet_ntoa(MyIP));
}

(결과)
IP : 211.179.80.239
(결과해석)
입력값인 0xef50b3d3을 바로 해석하면 239.80.179.211이 됩니다. 즉, 결과값은 호스트 바이트 오더를 따르는것을 알 수 있습니다.


** 이 글의 저작권은 모두 저자에게 있습니다.
   수정, 배포시 저작권을 표시해주시기 바랍니다.
** 오타, 잘못된 내용이 있으면 적극적으로 알려주시기 바랍니다 :)
** 질문사항 또한 적극적으로 받겠습니다.

Copyright (c) NEWMS 2007 All right Reserved.
크리에이티브 커먼즈 라이선스
Creative Commons License
Write your message and submit
« PREV : 1 : ... 27 : 28 : 29 : 30 : 31 : 32 : 33 : 34 : 35 : NEXT »