네트워크 프로그래밍 3주차

Hyun·2024년 10월 13일
0

3.1. 소켓 주소 구조체

  • 필요한 주소 정보를 담는 구조체.
  • 다양한 소켓 함수의 인수로 사용.
  • 기본형은 sockaddr 구조체.
  • 응용 프로그램이 사용할 프로토콜의 종류에 따라 별도의 소켓 주소 구조체가 정의되어 있음. (TCP/IP => sockaddr_in{} or sockaddr_in6{})
#include <winsock2.h>

struct sockaddr {
	unsigned short 	sa_family;
    char 	sa_data[14];
};
  1. sa_family:
  • 주소 체계를 나타내는 16비트 (2바이트) 정수 값 (TCP/IP => AF_INET, AF_INET6)
  • 소켓 생성 함수의 첫번째 파라미터
SOCKET socket(
	int af, // <= 주소 체계 
    int type,
    int protocol,
); 
  1. sa_data
  • 해당 주소 체계에서 사용할 주소 정보 (14 바이트) (TCP/IP 프로토콜 => IP 주소, 포트)

3.1.1. sockaddr_in 구조체 - IPv4 전용

#include <winsock2.h>
#include <netinet/in.h>

struct sockaddr_in {
	short 	sin_family; // AF_INET (IPv4)
    unsigned short 	sin_port; // Port number
    struct in_addr sin_addr; // IPv4 주소 (4 바이트, 32 비트)
    char sin_zero[8]; // 항상 0으로 설정
};

3.1.2. sockaddr_in6 구조체 - IPv6 전용

#include <ws2tcpip.h>
#include <netinet/in.h>

struct sockadd_in6 {
	short sin6_family; // AF_INET6 (IPv6)
    u_short sin6_portl // Port number
    u_long sin6_flowinfo; // 지원 X 필드 (0)
    struct in6_addr; // IPv6 주소 (16 byte, 128 비트)
    u_long sin6_scope_id // 인터페이스를 가리키는 인덱스 값, 대부분 0
   }

=> 포트 번호는 둘다 16비트, 두 프로토콜의 차이는 IP 주소 크기와 형식

  • IPv4 주소를 담는 in_addr 구조체는 32 비트 주소를 담는 s_addr 필드를 가진다.
  • IPv6 주소를 담는 in6_addr 구조체는 운영체제에 따라 공용체/배열로 구성된다.

3.1.3. 소켓 주소 구조체를 사용하는 두 가지 케이스

  1. 소켓 함수에 소켓 주소 정보 전달
  2. 소켓 함수로부터 소켓 주소 정보를 얻을 때
    => 소켓 주소 구조체는 주소 체계에 따라 다르기 때문에 기본형인 sockaddr의 포인터 타입으로 타입 캐스팅을 해야 한다.

3.2. 바이트 정렬 함수

바이트 정렬: 메모리에 데이터를 저장할 때의 바이트 배치 순서

  • 빅 엔디언: 최상위 바이트부터 저장
  • 리틀 엔디언: 최하위 바이트로부터 저장

ex) 0x12345678 메모리에 저장할 때

바이트 정렬 방식을 고려해야 하는 경우

  • 프로토콜 구현을 위해 필요한 컨트롤 정보는 빅 엔디언으로 통일
  • 응용 프로그램이 주고받는 데이터는 서로 간에 동일한 방식

네트워크 바이트 정렬(n): 빅 엔디안 방식
호스트 바이트 정렬(h): 시스템이 사용하는 고유한 바이트 정렬 방식

#include <winsock2.h>

u_short htons(u_short hostshort); // host-to-network-short (2바이트)
u_long htonl(u_long hostlong); // host-to-network-long(4 바이트)
u_short ntohs(u_short netshort); // network-to-host-short(2 바이트)
u_long ntohl(u_long netlong); // network-to-host-long(4 바이트)
  • 2바이트(short)는 port를 변환할 때 사용
  • 4바이트(long)는 IP를 변환할 때 사용

바이트 정렬 함수 사용 상황

  • hton*() 함수는 응용 프로그램이 소켓 함수에 데이터를 넘겨주기 위해 호출
  • ntoh*() 함수는 소켓 함수가 결과로 리턴한 데이터를 응용 프로그램이 출력 등의 목적으로 사용하기 전에 호출

3.3. IP 주소 변환 함수

  • 문자로 된 IP 주소를 32비트(IPv4) 또는 128비트(IPv6) 숫자로 변환해야 함.
  • 또는 반대로, 32비트(IPv4) 또는 128비트(IPv6) 숫자를 문자로 된 IP 주소로 변환해야 하는 경우도 있음

inet_addr: 문자열 형태로 IPv4 주소 입력 => 32비트 숫자(네트워크 바이트 정렬)로 리턴
inet_ntoa: 32비트 숫자(네트워크 바이트 정렬)로 IPv4 주소 입력 => 문자열 형태로 리턴

#include <ws2tcpip.h>
int inet_pton(int af, const char *src, void *dst);
const char *inet_ntop(int af, const void *src, char *dst, size_t size);

inet_pton: 주소체계 & 문자열 형태의 주소 입력 => 숫자(네트워크 바이트 정렬) 형태로 리턴
inet_ntop: 주소체계 & 숫자(네트워크 바이트 정렬) 형태의 주소 입력 => 문자열 형태로 주소 리턴

바이트 정렬 함수와 IP 주소 변환 함수 사용 예

  1. 응용 프로그램이 소켓 주소 구조체를 초기화, 소켓 함수에 넘겨주는 경우 (pton 사용, 문자를 네트워크 정렬 기반 숫자로)
  2. 소켓 함수가 소켓 주소 구조체를 입력으로 받아 내용을 채우면 응용 프로그램이 이를 출력 등의 목적으로 사용 (ntop 사용, 네트워크 정렬 기반 숫자를 문자로)

윈도우 전용 주소변환 함수 (문자열 -> 숫자)

int WSAStringToAddress(
	LPTSTR AddressString, // 문자열 형식의 IP 주소
    INT AddressFamily, // AF_INET 또는 AF_INET6
    LPWSAPRTOCOL_INFO IpProtocolInfo, // 생성되는 소켓의 특성 정보를 담고 있는 WSAPROTOCOL_INFO 구조체, 기본은 NULL
    LPSOCKADDR IpAddress, // IP 주소(숫자)를 저장할 구조체 (SOCKADDR_IN 또는 SOCKADDR_IN6)
    LPINT IpAddressLength
    // 주소 구조체의 길이
 );

윈도우 전용 주소변환 함수 (숫자 -> 문자열)

int WSAAddressToString(
	LPSOCKADDR IpsaAddress, // 숫자형식의 IP 주소 (SOCKADDR_IN 또는 SOCKADDR_IN6)
    DWORD dwAddressLength, // 주소 구조체의 길이
    LPWSAPROTOCOL_INFO IpProtocolInfo, // 생성되는 소켓의 특성 정보를 담고 있는 WSAPROTOCOL_INFO 구조체, 기본은 NULL
    LPTSTR IpszAddressString, // IP 주소(문자열)을 저장할 버퍼
    LPDWORD IpdwAddressStringLength // 버퍼의 길이
   );

4. DNS와 이름 변환 함수

도메인 이름: IP 주소처럼 호스트나 라우터의 고유한 식별자,
IP 주소보다 기억하고 사용하기 쉬움

  • 도메인 이름을 반드시 숫자 형태의 IP 주소로 변환해야 함

도메인 이름 <=> IP 주소 변환 함수

#include <winsock2.h>
#include <netdb.h>

// 도메인 이름 -> IP 주소 (네트워크 바이트 정렬)
struct hostent *gethostbyname(
	const char *name // 도메인 이름
);

struct hostent *gethostbyaddr(
	const char *addr, // IP 주소 (네트워크 바이트 정렬) 
    int	 len, // IP 주소의 길이
    int	 type // 주소 체계 (AF_INET 또는 AF_INET6)
   );

hostent 구조체

struct hostent {
	char *h_name; // 공식 도메인 이름
    char **h_aliases; // 공식 이외 도메인 이름들 (별명)
    short h_addrtype; // 주소 체계 ex. AF_INET
    short h_length; // 주소의 크기 (바이트 단위)
    char **h_addr_list; // 도메인 이름에 대한 IP 주소 list
   #define h_addr h_addr_list[0] // 여러 IP 중 첫번쨰 IP의 주소, 구 버전과의 호환을 위해서 
 };

hostent 구조체 - IPv4를 사용하는 경우

hostent 구조체 - IPv6를 사용하는 경우

사용자 정의 함수
1. 도메인 이름 -> IPv4 주소
gethostbyname()
2. IPv4 주소 -> 도메인 이름
gethostbyaddr()

0개의 댓글

관련 채용 정보