소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

32
소켓 주소 구조체 다루기 NHN NEXT 장문익

Upload: -

Post on 05-Jul-2015

361 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

소켓 주소 구조체 다루기

NHN NEXT 장문익

Page 2: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

소켓 주소 구조체(socket address structures)

네트워크 프로그램에서 필요로 하는 주소 정보를 담고 있는 구조체

다양한 소켓 함수의 인자로 사용한다.

여러 소켓 주소 구조체 중 가장 기본이 되는 것은 SOCKADDR

Page 3: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

socket address structure

struct sockaddr {

u_short sa_family;

char sa_data[14];

};

typedef struct sockaddr SOCKADDR;

sa_family: 주소 체계를 나타내며, 부호 없는

16비트 정수값을 사용한다.

TCP/IP 프로토콜을 사용한다면 이 값은

AF_INET이 된다.(당연한 말이다. AF_INET는

TCP/IP를 사용하기 위한 주소체계니까)

sa_data[14]: 해당 주소 체계에서 사용하는

주소 정보를 담고 있다. 주소 체계에 따라 필요

한 정보가 다르다.

가장 일반적인 형태는 바이트 배열

TCP/IP 프로토콜을 사용하면 여기에는 IP 주소

와 포트 번호가 저장된다.

Page 4: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

TCP/IP 프로토콜을 위한 SOCKADDR_IN

struct sockaddr_in {

short sin_family;

u_short sin_port;

struct in_addr sin_addr;

char sin_zero[8];

};

typedef struct sockaddr_in SOCKADDR_IN;

sin_family: 주소 체계. 부호 있는 16비트 정수

값 사용. 항상 AF_INET값 사용.

sin_port: 포트 번호. 부호없는 16비트 정수값.

sin_addr: IP 주소. 32비트 in_addr 구조체.

sin_zero: 실제로 사용하지는 않음. 항상 0으로

채움

Page 5: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

IP 주소를 저장하는 in_addr 구조체

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

u_long S_addr;

} S_un;

#define s_addr S_un.S_addr

};

typedef struct in_addr IN_ADDR;

Page 6: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

소켓 주소 구조체 사용

소켓 주소 구조체를 초기화한 후 소켓 함수에 넘겨주는 경우( f()는 소켓 함수)

SOCKADDR_IN addr1;

// 소켓 주소 구조체 초기화

...

f(( SOCKADDR* ) &addr1, ...); // 소켓 함수

// 소켓 주소 구조체의 크기가 크기 때문에

// 소켓 함수 인자로 주소값을 넘긴다.

Page 7: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

소켓 주소 구조체 사용

소켓 함수가 소켓 주소 구조체를 입력으로 받아서 초기화하고,

애플리케이션이 이를 출력 등의 목적으로 사용하는 경우( g()는 소켓함수)

SOCKADDR_IN addr2;

f(( SOCKADDR* ) &addr2, ...);

// 소켓 주소 구조체를 사용한다.

...

Page 8: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

바이트 정렬 함수

byte ordering

메모리에 데이터를 저장할 때의 바이트 순서를 나타내는 용어

big-endian: MSB(Most Significant Byte)부터 차례로 저장되는 방식

little-endian: LSB(Least Significant Byte)부터 차례로 저장되는 방식

Page 9: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

big-endian, little-endian

Page 10: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

byte ordering이 약속되어야 하는 이유1

IP 주소, 포트 번호 등과 같이 프로토콜 구현을 위해 필요한 정보

종단 시스템이 보낸 패킷의 IP 헤더에는 IP 주소가 포함되어 있고, 이 패킷을 라우터가 받으면, IP 주

소를 참조하여 다음 위치의 라우터에 보낸다.

byte-ordering을 약속하지 않으면 IP 주소 해석이 달라져서 잘못된 라우팅이 될 수 있다.

Page 11: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

byte ordering이 약속되어야 하는 이유2

포트 번호의 바이트 정렬 방식

두 종단 시스템이 포트 번호의 바이트 정렬 방식을 약속하지 않을 경우, 잘못된 목적지 프로세스에

데이터가 전달될 수 있다.

Page 12: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

network byte ordering

IP 주소와 포트 번호의 바이트 정렬방식이 약속되지 않으면 앞의 문제가 발생한다.

그래서 IP 주소와 포트 번호의 바이트 정렬방식은 big-endian으로 통일하여 사용한다.

네트워크 용어로 big-endian을 network byte ordering이라 한다.

시스템이 사용하는 고유한 byte ordering을 host byte ordering이라 부른다.

Page 13: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

byte ordering이 약속되어야 하는 이유3

애플리케이션이 주고 받는 데이터

두 종단 시스템이 교환하는 데이터에 대해 byte ordering이 약속되지 않으면, 데이터 해석의 문제

가 발생할 수 있다.

대게 network byte ordering을 사용한다.

Page 14: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hton*()

윈속에서 제공하는 byte ordering 유틸리티 함수

host byte ordering로 저장된 값을 입력으로 받아서 network byte ordering으로 변환한 값을 리턴

한다.

함수 이름은 ‘H’ost ‘T’o ‘N’etwork u_’S’hort 방식으로 지었다고 추측한다.

u_short htons( u_short hostshort ); // host-to-network-short

u_long htons( u_long hostong ); // host-to-network-long

Page 15: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

ntoh*()

network byte ordering으로 저장된 값을 입력으로 받아서 host byte ordering으로 변환한 값을 리

턴한다.

u_short ntohs( u_short networkshort ); // network-to-host-short

u_long ntohs( u_long networkshort ); // network-to-host-long

Page 16: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hton*()함수와 ntoh*()함수 호출

Page 17: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

winsock 2.x에서 제공하는 byte ordering 함수

int WSAHtons ( SOCKET s, u_short hostshort, u_short* lpnetshort );

int WSAHtonl ( SOCKET s, u_long hostlong, u_long* lpnetlong );

int WSANtohs ( SOCKET s, u_short netshort, u_short* lphostshort );

int WSAHtohs ( SOCKET s, u_long netlong, u_long* lphostlong );

첫 번째 인자는 소켓 디스크럽터

변환된 결과는 함수 리턴값이 아닌 세 번째 인자로 전달한다.

Page 18: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

SOCKADDR_IN 구조체의 byte ordering

sin_family는 host byte ordering을 따른다.

sin_port와 sin_addr은 network byte ordering을 따른다.

Page 19: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hton*(), ntoh*() 사용 시 주의할 점

u_short x = 0x1234;

// 잘못된 사용

printf("wrong!\n");

printf("0x%x -> 0x%x\n", x, htonl(x));

htol() 함수는 u_long을 리턴한다.

u_short를 전달하여 u_long을 리턴하므로, 남

는 4byte는 0으로 채워진다.

결과

wrong!

0x1234 -> 0x34120000

Page 20: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

IP 주소 변환 함수

윈도우 애플리케이션에서는 IP 주소를 입력 받기 위해 cmd와 edit contro을 이용한다고 한다.

이때 애플리케이션은 IP 주소를 문자열 형태로 전달받게 되므로 이를 32비트 숫자로 변환해야 한다.

inet_addr() 함수는 문자열 형태로 IP 주소를 입력받아 32비트 숫자(network byte ordering)로 리

턴한다.

inet_ntoa() 함수는 32비트 숫자(network byte ordering)로 IP 주소를 입력받아 문자열 형태로 리

턴한다.

Page 21: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

inet_addr()와 inet_ntoa()

unsigned long inet_addr( const char *cp );

char* inet_ntoa( struct in_addr in ); // network-to-ascii

Page 22: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

바이트 정렬 함수와 IP 주소 변환 함수 예시1

// 소켓 주소 구조체 초기화

SOCKADDR_IN addr;

ZeroMemory( &addr, sizeof( addr ) );

addr.sin_family = AF_INET;

addr.sin_addr.s_addr =inet_addr( "147.46.114.70" );

addr.sin_port = htons( 9010 );

// 소켓 함수 호출

f( ( SOCKADDR * )&addr, ... );

inet_addr() 함수는 이미 network byte ordering된 IP 주소를 리턴하므로 htonl() 함수를 적용하면 안 된다.

// wrong!

addr.sin_addr.s_addr =htonl(inet_addr( "147.46.114.70" ));

Page 23: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

바이트 정렬 함수와 IP 주소 변환 함수 예시1

// 소켓 함수 호출

g( ( SOCKADDR *)&addr, ... );

// IP 주소와 포트 번호 출력

printf("IP 주소 = %s, 포트 번호 = %d",

inet_ntoa( addr.sin_addr ), ntohs( addr.si

n_port ) );

addr.sin_addr은 이미 network byte orderin

된 IP 주소이므로 ntohl() 함수를 적용하면 안

된다.

// error

printf("IP 주소 = %s, 포트 번호 = %d",

inet_ntoa( htonl( addr.sin_addr ) ),

ntohs( addr.sin_port ) );

심지어 자료형도 맞지 않다.

Page 24: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

도메인 이름 시스템과 이름 변환 함수

domain name

IP 주소와 대응하는 이름으로, 사람이 기억해서 사용하기 쉽게 만든 것

TCP/IP 프로토콜은 도메인 이름을 인식하지 못하므로 사용자가 입력한 도메인 이름을 반드시 IP 주

소로 변환해야 한다.

IP 주소와 도메인 이름 사이의 변환 정보는 인터넷에 연결된 여러 개의 도메인 이름 서버(DNS

Server, Domain Name System Server)가 관리한다.

Page 25: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

도메인 이름-> IP주소(network byte ordering)

// domain name -> IP address(network byte ordering)

struct hostent* gethostbyname(

const char *name // domain name

);

Page 26: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

IP 주소(network byte ordering) -> 도메인 이름

// IP address(network byte ordering) -> domain name

struct hostent* gethostbyaddr(

const char *addr, // IP address(network byte ordering)

int len, // IP address 길이

int type // 주소 체계(예 : TCP/IP의 경우는 AF_INET)

);

Page 27: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hostent 구조체

typedef struct hostent {

char* h_name; // official name of host

char** h_aliases; // alias list

short h_addrtype; // host address type

short h_length; // length of address

char** h_addr_list; // list of addresses

#define h_addr h_addr_list[0] // addrss, for backward compatibilty

} ;

typedef struct hostent HOSTENT;

Page 28: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hostent 구조체

h_name: 공식 도메인 이름

h_aliases: 한 호스트가 공식 도메인 이름 외에 다른 이름을 여러 개 가질 수 있으며, 이를 별명(alias

name)이라 부른다.

h_addrtype: 주소체계를 나타내는 상수값. IPv4를 사용하는 경우 AF_INET.

h_length: IP 주소의 길이(바이트 단위). IPv4를 사용하는 경우 4(32비트)가 저장된다.

h_addr_list: network byte ordering 된 IP 주소를 나타낸다. 한 호스트가 여러 IP 주소를 가진 경우,

이 포인터를 따라가면 모든 IP 주소를 얻을 수 있다. 특정 호스트에 접속할 때는 대개 첫 번째 IP 주소

만 이용하므로 h_addr_list[0]를 접근하게 되는데, 매크로를 이용하여 재정의한 h_addr을 사용하면

편리하다.

Page 29: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

hostent 구조체

Page 30: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

gethostbyname() 함수를 이용한 유틸리티 함수

// domain name -> IP address

BOOL GetIPAddr( char* name, IN_ADDR* addr )

{

HOSTENT* ptr = gethostbyname(name);

if ( ptr == NULL ) {

err_display( "gethostbyname()" ); // error 출력 함수

return FALSE;

}

memcpy( addr, ptr->h_addr, ptr->h_length );

return TRUE;

}

Page 31: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

gethostbyaddr() 함수를 이용한 유틸리티 함수

// IP address -> domain name

BOOL GetDomainName( IN_ADDR* addr, char* name)

{

HOSTENT* ptr = gethostbyaddr( (char *)&addr, sizeof(addr), AF_INET );

if ( ptr == NULL ) {

err_display( "gethostbyaddr()" );// error 출력 함수

return FALSE;

}

strcpy( name, ptr->h_name );

return TRUE;

}

Page 32: 소켓 주소 구조체 다루기(윈도우 네트워크 프로그래밍)

참고자료

김선우. 윈도우 네트워크 프로그래밍. 한빛미디어