본문 바로가기

카테고리 없음

컴퓨터 네트워크 : Chapter 3. 주소 체계와 데이터 정렬

3-1. 소켓에 할당되는 IP주소와 PORT 번호

1) 인터넷 주소(Internet Address)

  • 인터넷 주소란?
    • 인터넷 상에서 컴퓨터를 구분하는 목적으로 사용되는 주소
    • 4바이트 주소체계인 IPv4와 16바이트 주소체계인 IPv6가 존재
    • 소켓을 생성할 때 기본적인 프로토콜을 지정해야 한다.
    • 네트워크 주소와 호스트 주소로 나뉜다. 네트워크 주소를 이용해서 네트워크를 찾고, 호스트 주소를 이용해서 호스트를 구분

2) 클래스 별 네트워크 주소와 호스트 주소의 경계(SKIP)

때문에 첫 번째 바이트 정보만 참조해도 IP 주소와 클래스 구분이 가능하며, 이로 인해서 네트워크 주소와 호스트 주소의 경계 구분이 가능

3) 소켓 구분에 활용되는 PORT번호

  • PORT번호
    • PORT번호는 16비트로 표현, 따라서 그 값은 0 이상 65535 이하
    • 0 ~ 1023은 잘 알려진 PORT(Well-known PORT)라 해서 이미 용도가 결정되어 있다.
    • PORT번호와 소켓이 1 대 1 매핑이 된다고 일단 생각하기

PORT번호에 의한 소켓의 구분과정

 

3-2 주소 정보의 표현

1) IPv4 기반의 주소표현을 위한 구조체

  • IP주소와 PORT 번호는 구조체 sockaddr_in의 변수에 담아서 표현한다.
struct sockaddr_in
{
	sa_family_t		sin_family;	 // 주소체계(버전에 대한 정보)
    uint16_t		sin_port;		// 포트 번호
    struct in_addr	sin_addr;		// 32비트 IP 주소
    char			sin_zero[8];	// 사용되지 않음
};

struct in_addr
{
	in_addr_t	s_addr;
}; // 32비트 IPv4 인터넷 주소
IP 주소는 원래 32bit 짜리 정수인데 이를 binary로 바꿔서 1 바이트씩 귾어서 표한 한 것이 우리가 평소에 알고 있는  165.246.32.46같은 형식이다.

2) 구조체 sockaddr_in의 멤버에 대한 분석

  • 멤버 sin_family : 주소체계 정보 저장

  • 멤버 sin_port : 16비트 port번호 저장 / 네트워크 바이트 순서로 저장
  • 멤버 sin_addr : 32비트 IP주소정보 저장 / 네트워크 바이트 순서로 저장
                             멤버 sin_addr의 구조체 자료형 in_addr 사실상 32비트 정수자료형
  • 멤버 sin_zero : 특별한 의미를 지니지 않는 멤버 / 반드시 0으로 채워야 함

3) 구조체  sockaddr_in의 활용의 예

  • 구조체 sockaddr_in은 bind 함수의 인자로 전달되는데, 매개변수 형이 sockaddr이므로 형 변환을 해야 한다.
struct sockaddr_in serv_addr;

if(bind(serv_sock, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == -1)
	error_handling("bind() error");
  • 구조체 sockaddr은 다양한 주소체계의 주소정보를 담을 수 있도록 정의됨
    → 그래서 IPv4의 주소정보를 담기가 불편함 
    → 동일한 바이트 열을 구성하는 구조체 sockaddr_in이 정의되었으며, 이를 이용해서 쉽게 IPv4의 주소정보를 담을수 있다.
struct sockaddr
{
	sa_family_t		sin_family;		// 주소체계(Address Family)
    char			sin_data[14];	// 주소 정보
};

 

3-3 네트워크 바이트 순서와 인터넷 주소 변환

1) CPU에 따라 달라지는 정수의 표현

  • CPU에 따라서 데이터를 표현 및 해석하는 방식이 다름

(1) Big Endian(빅 엔디안) : 상위 바이트의 값을 작은 번지수에 저장

(2) Little Endian(리틀 엔디안) : 상위 바이트의 값을 큰 번지수에 저장

(3) 호스트 바이트 순서 : CPU별 데이터 저장방식을 의미

(4) 네트워크 바이트 순서 : 통일된 데이터 송수신 기준을 의미 / 빅 엔디안이 기준

2) 바이트 순서의 변환

  • h : 호스트(host) 바이트 순서를 의미
  • n : 네트워크 바이트 순서를 의미 → 내가 쓰는 컴퓨터가 빅 엔디안이든 리틀 엔디안이든 네트워크 바이트 순서로 통일
  • s : 자료형 short를 의미
  • l : 자료형 long을 의미
unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long htonl(unsigned long);
unsigned long ntohl(unsigned long);

<예시>

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;
}

 

3-4. 인터넷 주소의 초기화와 할당

1) 문자열 정보를 네트워크 바이트 순서의 정수로 변환

  • "211.214.107.99"와 같이 점이찍힌 10진수로 표현된 문자열을 전달하면, 해당 문자열 정보를 참조하여 IP주소정보를 32비트 정수형으로 반환!
#include <arpa/inet.h>
in_addr_t inet_addr(const char * string);
→ 성공 시 빅 엔디안으로 변환된 32비트 정수 값, 실패 시 INADDR_NONE 반환

2) inet_aton

  • 기능사응로 inet_addr 함수와 동일 → in_addr형 구조체 변수에 변환의 결과가 저장된다는 점이 다름
#include <arpa/inet.h>
int inet_aton(const char * string, struct in_addr * addr);
→ 성공 시 1(true), 실패 시 0(false) 반환
// string : 변환할 IP주소정보를 담고 있는 문자열의 주소 값 전달
// addr : 변환된 정보를 저장할 in_addr 구조체 변수의 주소 값 전달

3) inet_ntoa

  • inet_aton 함수의 반대 기능 제공 → 네트워크 바이트 순서로 정렬된 정수형 IP주소정보를 우리가 눈으로 쉽게 인식할 수 있는 문자열의 형태로 변환
#include <arpa/inet.h>
char* inet_ntoa(struct in_addr adr);
→ 성공 시 변환된 문자열의 준소 값, 실패 시 -1 반환