IPv4 기준을 4바이트 IP 주소는 네트워크 주소와 호스트 주소로 나뉘며, 주소의 형태에 따라서 클래스가 분류된다. 네트워크 주소를 통해 라우터를 찾고 나머지 호스트 주소를 이용해 호스트에 접근한다.
라우터는 외부와 호스트의 데이터 전송을 목적으로 하는 일종의 컴퓨터이다.
클래스 A의 첫 번째 바이트 범위 0~127
클래스 B의 첫 번째 바이트 범위 128~191
클래스 C의 첫 번째 바이트 범위 192~223, 과 같이 클래스 별 IP 주소의 경계를 나누어 놓았다.
이는 첫 번째 바이트만 보면 네트워크 주소가 몇 바이트인지 판단이 가능하도록 한다.
A의 경우 첫 비트가 항상 0으로, B의 경우 10, C의 경우 110으로 시작한다.
주소정보를 위해서 세가지가 필요하다 : 주소체계, IP주소, 포트번호
다음의 구조체는 bind 함수에 주소 정보를 전달하는 용도로 사용된다.
struct sockaddr_in
{
sa_family_t sin_family // 주소체계(Address Family)
uint16_t sin_port; // 16비트 포트번호
struct in_addr sin_addr; // 32비트 IP주소
char sin_zero[8] // 형 변환을 위해 필요
};
struct in_addr
{
in_addr_t s_addr; // 32비트 IPv4인터넷 주소
};
정수 0x1234를 저장하는 방식을 살펴보자, Big Endian의 경우 0x34(1번지) 0x12(2번지)
Little Endian의 경우 0x12(1번지) 0x34(2번지)에 저장된다.
Little Endian의 경우 뒤에서부터 떼서 스택에 쌓는다고 생각하고, Big의 경우 앞에서부터 떼서 스택에 쌓는다고 생각하면된다.
네트워크 바이트 순서는 Big Endian으로 통일되어있고, 호스트 바이트 순서가 이에 맞추면 된다. 이는 소켓이 알아서 진행 해준다.
endian_conv.c
#include <stdio.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
unsigned short host_port=0x1234;
unsigned short net_port;
unsigned long host_addr=0x12345678;
unsigned long net_addr;
net_port=htons(host_port);
net_addr=htonl(host_addr);
printf("Host ordered port: %#x \n", host_port);
printf("Network ordered port: %#x \n", net_port);
printf("Host ordered address: %#lx \n", host_addr);
printf("Network ordered address: %#lx \n", net_addr);
return 0;
}