소켓 주소 구조체

bolee·2022년 4월 5일
0

소켓 주소 구조체(docket address structures)란?

  • 네트워크 프로그램에서 필요한 주소 정보를 담고 있는 구조체로, 다양한 소켓 함수의 인자로 사용된다.
  • 프로토콜 체계에 따라 주소 지정 방식이 다르기 때문에 다양하 ㄴ소켓 주소 구조체가 존재한다.

SOCKADDR

기본적으로 사용되는 소켓 주소 구조체는 SOCKADDR 구조체로, ws2def.h 파일(winsock2.h 파일에 포함)에 아래 처럼 정의 되어 있다.

typedef struct sockaddr
{
	u_short	sa_family;		// u_short: unsigned short
    char	sa_data[14];
}	SOCKADDR;
  • sa_family: 주소 체계를 나타내는 16비트 정수 값. 예를 들어 TCP/IP 프로토콜의 경우 AF_INET 또는 AF_INET6
  • sa_data[14]: 해당 주소 체계에서 사용할 주소 정보. 주소 체계에 따라 필요한 정보가 다르기 때문에 가장 일반적인 형태인 바이트 배열로 선언되어 있다. 예를 들어 TCP/IP 프로토콜의 경우 IP 주소와 포트 번호가 저장

응용 프로그램이 사용할 프로토콜의 종류에 맞는 별도의 소켓 구조체를 사용해야 한다.
예를 들어 TCP/IP에서는 SOCKADDR_IN 또는 SOCKADDR_IN6를 사용하고, IrDA(Infrared Data Association; 적외선을 통한 무선 통신 프로토콜)에서는 SOCKADDR_IRDA를 사용한다.

SOCKADDR_IN, SOCKADDR_IN6

주로 사용되는 TCP/IP 프로토콜을 위한 소켓 주소 구조체는 IP 버전에 따라 두 종류 이며, 각각 ws2def.h(winsock2.h파일에 포함)과 ws2ipdef.h(ws2tcpip.h 파일에 포함)파일에 다음과 같이 정의되어 있다.

/* IPv4 소켓 주소 구조체 */
typedef struct sockaddr_in
{
	short			sin_family;
    u_short			sin_port;
    struct in_addr	sin_addr;
    char			sin_zero[0];	// 대부분 0으로 설정
}	SOCKADDR_IN;

/* IPv6 소켓 주소 구조체 */
typedef struct sockaddr_in6
{
	short			sin6_family;
    u_short			sin6_port;
    u_long			sin6_flowinfo;	// 대부분 0으로 설정
    struct in6_addr	sin6_addr;
    u_long			sin6_scope_id;	// 대부분 0으로 설정	
}	SOCKADDR_IN6;
  • sin_family, sin6_family: 주소 체계를 의미하며, 각각 AF_INET, AF_INET6 값을 사용한다.
  • sin_port, sin6_port: 포트 번호를 의미하며, 부호없는 16비트 정수값을 사용한다.
  • sin_addr, sin6_addr: IP 주소를 의미하며, 각가 32비트 in_addr 구조체와 128비트 in6_addr 구조체를 사용한다.

IP 주소를 저장하기 위한 in_addr 구조체와 in6_addr 구조체는 각각 inaddr.h(winsock2.h 파일에 포함)과 in6addr.h(ws2tcpip.h 파일에 포함)에 아래와 같이 정의 되어 있다.

typedef struct in_addr
{
	union
    {
    	struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b;
        struct { u_short s_w1, s_w2; } S_un_w;
        u_long S_addr;
    } S_un;
#define s_addr S_un.S_addr
}	IN_ADDR;

typedef struct in6_addr
{
	union
    {
    	u_char Byte[16];
        u_short Word[8];
    } u;
}	IN6_ADDR;

IPv4 주소를 담는 in_addr 구조체는 동일 메모리 영역을 각각 8비트(S_un_b), 16비트(S_un_w), 32비트(S_addr) 단위로 접근할 수 있게 만든 공용체(S_un)임을 알 수 있다. 응용 프로그램에서는 대개 32비트 단위로 접근하므로 S_un.S_addr 필들르 사용하여, 매크로를 통해 재정의된 s_addr을 사용하면 편하다.
in_addr 구조체와 달리 IPv6 주소를 담는 in6_addr 구조체는 단순한 파이트 또는 워드 배열로 정의되어 있다.

소켓 주소 구조체의 크기

소켓 주소 구조체의 크기가 아래 표에 정의 되어 있다. 위에서 살펴본 SOCKADDR, SOCKADDR_IN, SOCKADD_IN6 뿐만 아니라 IrDA 프로토콜에서 사용하는 SOCKADDR_IRDA와 블루투스 프로토콜에서 사용하는 SOCKADDR_BTH 구조체도 같이 표시했다.

구조체 이름전체 크기 (바이트 단위)
SOCKADDR16
SOCKADDR_IN16
SOCKADDR_IN628
SOCKADDR_IRDA32
SOCKADDR_BTH30

소켓 주소 구조체를 사용하는 상황

  1. 응용 프로그램이 소켓 주소 구조체를 초기화 하고 소켓 함수에 넘겨오는 경우(SocketFunc()은 임의의 소켓 함수)
    // 소켓 주소 구조테를 초기화
    SOCKADDR_IN addr;
    ...
    SocketFunc(..., (SOCKADDR *) &addr, sizeof(addr), ...);
  2. 소켓 함수가 소켓 주소 구조체를 입력으로 받아 내용을 채우면, 응용 프로그램이 이를 출력 등의 목적으로 사용하는 경우(SocketFunc()은 임의의 소켓 함수)
    SOCKADDR_IN addr;
    SocketFunc(..., (SOCKADDR *) &addr, sizeof(addr), ...);
    // 소켓 구조체를 사용한다.
    ...

주의 사항

  • 소켓 주소 구조체는 크기가 크기 때문에 소켓 함수 인자로 전달할 때는 항상 주소 값을 사용하며, 반드시 SOCKADDR 포인터 형으로 변환(type casting)해야 한다.
  • 사용할 프로토콜에 따라 소켓 주소 구조체의 크기가 달라지기 때문에 sizeof 연산자를 사용해 얻은 크기 정보를 같이 전달해야 한다.

참고 자료
김성우 저, "TCP/IP 윈도우 소켓 프로그래밍", 한빛아카데미, 2018

0개의 댓글