프로그래밍/예전글

네트워크의 주소체계와 데이터 정렬

Cat체셔 2010. 8. 17. 10:49

인터넷 주소(Internet Adress)
 - IPv4(Internet Protocol version 4) : 4바이트 주소체계(1234.1234.1234.1234)
 - IPv6(Internet Protocol version 6) : 16바이트 주소체계(1234.1234.1234.1234.1234.1234.1234.1234)
                                                         : IPv4의 IP주소가 모두 고갈될 것을 염려하여 만들었다.


IPv4기반의 주소표현을 위한 구조체
struct sockaddr_in
{
  sa_family_t      sin_family;    // 주소체계(Adress Family)
  uint16_t           sin_port;      // 16비트 TCP/UDP PORT번호
  struct in_addr  sin_addr;     // 32비트 IP주소
  char               sin_zero[8] // 사용되지 않음
};

struct in_addr
{
  in_addr_t  s_addr; //32비트 IPv4 인터넷 주소
};

 - 구조체 분석
멤버 변수
  sin_family
->프로토콜체계마다 적용하는 주소체계가 다르다. 예를 들어서 IPv4에서는 4바이트 주소체계를 사용하고 IPv6에서는 16비트 주소체계를 사용해야 한다.
->AF_INET    : IPv4 인터넷 프로토콜에 적용하는 주소체계(AF = Adress Family)
->AF_INET6   : IPv6 인터넷 프로토콜에 적용하는 주소체계
->AF_LOCAL : 로컬 통신을 위한 유닉스 프로토콜의 주소체계
  sin_port
->소켓의 구분에 활용되는 것이 바로 Port번호이다. IP만 있다면 목적지 컴퓨터로 데이터를 전송할 순 있어도 해당 응용프로그램까지 전송할 수는 없지 않은가?
->16비트의 PORT번호를 저장하는 변수이다. 단, '네트워크 바이트 순서'로 저장해야 한다(이것은 아래에 추가 설명을 해놓을 것입니다.),
  sin_addr
-> 32비트 IP주소를 저장한다. 이것 역시 '네트워크 바이트 순서'로 저장해야 한다.
  sin_zero
-> 단순히 구조체 sockaddr_in와 크기를 맞추기 위해 존재하는 변수이다. 반드시 0으로 초기화해주어야 한다.


struct sockaddr
{
  sa_family_t  sin_family;      // 주소체계(Address Family)
  char           sa_data[14];  // 주소정보
};
멤버변수
  sa_data[14]
->IP주소와 PORT번호를 담고 있어야 하고, 남은 부분은 0으로 채울것을 bind함수는 요구하고 있다. 그렇기 때문에 sockaddr_in이라는 구조체가 필요한 것이다.



네트워크 바이트 순서와 인터넷 주소 변환
CPU에 따라서 4바이트 메모리 공간에 정수 1을 저장하는 방식이 달라진다.
00000000 00000000 00000000 00000001   -> 빅엔디안    : 상위 바이트의 값을 작은 번지수에 저장하는 방식
00000001 00000000 00000000 00000000   -> 리틀엔디안 : 상위 바이트의 값을 큰 번지수에 저장하는 방식

0x12345678이라는 데이터를 전송할 경우
빅엔디안 ------------------------------------> 리틀 엔디안
   송신       0x78  ->  0x56  ->  0x34  ->  0x12            수신
0x12345678                                                        0x78563412

그래서 결국 빅엔디안 방식으로 통일하기로 약속을 하였다.


바이트 순서의 변환
 - unsigned short htons(unsigned short);
 - unsigned short ntohs(unsigned short);
 - unsigned long htonl(unsigned long);
 - unsigned long ntohl(unsigned long);
 여기서 h는 호스트(host)바이트 순서를 의미하고, n은 네트워크(network)바이트 순서를 의미한다.
 그리고 s는 short형을 의미하고, l은 long형을 의미한다.(to는 영어 to를 뜻함)
 그렇다면 이것을 가지고 위의 함수들을 해석하면 이렇게 된다.

 - unsigned short htons(unsigned short); short형 데이터를 호스트바이트 순서에서 네트워크바이트 순서로 변환해라.
 - unsigned short ntohs(unsigned short); short형 데이터를 네트워크바이트 순서에서 호스트바이트 순서로 변환해라.
 - unsigned long htonl(unsigned long); long형 데이터를 호스트바이트 순서에서 네트워크바이트 순서로 변환해라.
 - unsigned long ntohl(unsigned long); long형 데이터를 네트워크바이트 순서에서 호스트바이트 순서로 변환해라.



 sockaddr_in server;
 memset(&server,0,sizeof(server));
 server.sin_family = AF_INET;
 server.sin_port = htons(10000);
 server.sin_addr.S_un.S_addr = htonl(ADDR_ANY);
 bind(m_hServer, (sockaddr*)&server, sizeof(server));

 sockaddr_in client;
 memset(&client,0,sizeof(client));
 client.sin_addr.s_addr = inet_addr(IP);
 client.sin_family = AF_INET;
 client.sin_port = htons(Port);
 connect(m_hClient, (sockaddr*)&client, sizeof(client));

여태까지 배운것들이 이 12줄을 위해 배운거랍니다. 하하하;;;