Part1_주소 체계와 데이터 정렬(1)

·2023년 10월 29일
0

[IP 주소]

  • 인터넷상에 존재하는 호스트들을 구분하기 위한 32비트 주소 체계
  • 네트워크 주소와 호스트 주소로 나뉘며, 주소의 형태에 따라 A ~ E 클래스로 분류 가능
    • 네트워크 주소 : 네트워크를 구분하여 주는 ID

[Port]

  • 인터넷을 통해 데이터를 주고 받는 프로그램이 여러 개 실행되고 있더라도 데이터를 송/수신하는 길은 하나밖에 존재하지 않음
  • IP 주소로는 인터넷에 연결되어 있는 컴퓨터들을 구분하여 줄 수는 있어도 컴퓨터 안에서 실행되고 있는 프로그램까지 구분하여 주지는 못함 (수신한 패킷이 메신저 프로그램 패킷인지, 동영상 재생 프로그램의 패킷인지 구분 불가) → 이를 구분하기 위해 필요한 것이 Port
  • 2바이트로 표현되므로 0 ~ 65535까지 있음
    • 0 ~ 1023번 까지는 잘 알려진 포트임 (예약된 Port)
    • TCP 소켓과 UDP 소켓은 Port를 서로 공유하지 않으므로 중복 가능 (TCP 소켓을 생성할 때 9190 Port를 사용했다면, 다른 TCP 소켓은 9190 Port를 사용할 수 없지만, UDP 소켓은 사용 가능)

[주소 정보의 표현]

[IPv4의 주소 체계를 나타내는 구조체]

struct sockaddr_in
{
	sa_family_t    sin_family;   // 주소 체계
	uint16_t       sin_port;     // 16비트 TCP / UDP Port
	struct in_addr sin_addr;     // 32비트 IPv4 주소
	char           size_zero[8]; // 사용되지 않음
};

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

[POSIX(Potable Operating System Interface)]

Data typeDescriptionHeader
int8_t
uint8_t
int16_t
uint16_t
int32_t
uint32_t
signed 8-bit int
unsigned 8-bit int (unsigned char)
signed 16-bit int
unsigned 16-bit int (unsigned short)
signed 32-bit int
unsigned 32-bit int (unsigned long)
<sys/types.h>
sa_family_t
socklen_t
address family
length of struct
<sys/socket.h>

[Local Unix 프로토콜에서 사용되는 주소 정보 구조체]

struct sockaddr_un
{
	sa_family_t sun_family;    // 주소 체계
	char        sun_path[108]; // 경로 이름
}

[sockaddr_in 구조체 정보]

  • sin_family
    • 사용되는 주소 체계에 대한 정보 대입(프로토콜 체계마다 주소 체계가 다름)

      주소 체계정의
      AF_INETIPv4 인터넷 프로토콜
      AF_INET6IPv6 인터넷 프로토콜
      AF_LOCALLocal 통신을 위한 UNIX 프로토콜
  • sin_port : 16비트 Port 정보를 대입해 줌. 네트워크 바이트 순서로 대입해야 함
  • sin_addr : 32비트 IP 주소 정보를 대입해 줌. 네트워크 바이트 순서로 저장해야 함
  • sin_zero : 특별한 의미 없이 단순한 채워주기(padding) 목적으로 사용되는 구조체 멤버

[네트워크 바이트 순서]

  • 시스템 내부적으로 데이터를 표현하는 방법
  • sockaddr_in 구조체 변수에 값을 대입할 경우 네트워크 바이트 순서로 값을 변경한 다음 대입해야 함
  • 크게 두 가지 방법으로 나뉨
    • Big-Endian 상위 바이트의 값이 메모리상에 먼저(번지수가 작은 위치) 표시되는 방법
    • Little-Endian 하위 바이트의 값이 메모리상에 먼저(번지수의 작은 위치) 표시되는 방법
  • 시스템 내부적으로 데이터를 처리하는 데 있어 어떤 방식을 쓸지는 CPU에 따라 달라짐 → 이를 호스트 바이트 순서라 함
    • 문제는 호스트 바이트 순서가 일정치 않음
    • 이러한 문제 때문에 네트워크를 통해 데이터를 전송할 때는 통일된 방식을 이용해서 데이터를 전송하기로 약속함 → 네트워크 바이트 순서(Big-Endian)

[바이트 순서 변환 함수]

#include <netinet/in.h>

unsigned short htons(unsigned short);
unsigned short ntohs(unsigned short);
unsigned long htonl(unsigned short);
unsigned long ntohl(unsigned short);

// h : host byte order
// n : network byte order
// s : short (16bit)
// l : long (32bit)

htonl은 Host Byte 순서를 Network Byte 순서로 바꾸는 함수를 의미

뒤의 l은 long 타입을 의미

→ 32비트 데이터를 호스트 바이트 순서에서 네트워트 바이트 순서로 바꾸어 주는 함수


[임의의 데이터를 네트워크/호스트 바이트 순서로 출력]

#include <stdio.h>

int main(int argc, char** argv)
{
	short host_port_order = 0x1234;
	short net_port_order;

	long host_add_order = 0x12345678;
	long net_add_order;

	net_port_order = htons(host_port_order);
	net_add_order = htonl(host_add_order);

	printf(" Host ordered port : %x \n", host_port_order);
	printf(" Network ordered port : %x \n\n", net_port_order);
	
	printf(" Host ordered Address : %x \n", host_add_order);
	printf(" Network ordered Address : %x \n\n", net_add_order);

	return 0;
}

자신이 쓰고 있는 시스템이 Big-Endian 방식을 쓰고 있다 하더라도 반드시 변환 함수를 사용해서 네트워크 바이트 순서로 변환하는 과정을 거쳐야함

→ 이식성을 좋게 하기 위해

[결과]

네트워크 바이트 순서로 변환해서 출력한 결과, 호스트 바이트 순서의 출력 결과와 반대임 → Little-Endian 방식을 쓰고 있음

0개의 댓글