WINSOCK 의 헤더와 라이브러리
일반적으로 새로 응용 프로그램을 개발하고자 한다면WIN-SOCK2.H 를 include 하여 윈속2 로 개발
Window CE 와 같은 환경에서 이전 버전의 윈속과의 호환을 원한다면 WINSOCK.H 를 사용할 수 있음
WIN-SOCK2.H 를 프로그래밍 할 때는 WS2_32.LIB 파일을 링크
WIN-SOCK.H 를 사용할때는 WSOCK32.LIB 를 링크
윈속 초기화
모든 WINSOCK 프로그램은 적절한 버전의 윈속 DLL을 로드. 만일 윈속 라이브러리를 로드하지 않고 윈속 API 를
사용하면 SOCKET_ERROR 가 리턴
윈속 라이브러리의 로드는 WSAStartup 함수를 호출함으로서 이루어짐
int WSAStartup( WORD wVersionRequested , LPWSADATA lpWSAData );
wVersionRequested 는 로드하기를 원하는 윈속 라이브러리 버전을 지정
상위바이트는 윈속의 마이너 버전을 하위바이트는 메이져 버전을 의미한다.
MAKEWORD(x, y) 매크르로를 통해서 wVersionRequested를 입력.
lpWSAData 는 LPWSADATA의 포인터로 WSAStartup 은 로드된 라이브러이에 대한 정보가 리턴
typedef struct WSAdata
{
WORD wVersion; // 앞으로 사용될 윈속의 버전이 리턴
WORD WHighVersion; // 윈속 라이브러리가 사용할 수 있는 가장 높은 버전을의미
char szDescription[WSADESCRIPTION_LEN + 1]; // 벤더 ID 와 char szSystemStatus[WSADESCRIPTION_LEN + 1]; // 윈속 구현에 관련된 정보
unsigned short iMaxSocket; // 동시에 열수 있는 소켓의 개수
unsigned short iMsxUdpDg; // 데이터 그램의 최대 크기 ( WSAEnumProtocols 함수를 통해서 얻음 )
char FAR* LPWSADATA; // 윈속을 구현한 벤더에 관련한 정보를 위하여 예약된 피드
}
응용 프로그램에서 윈속 인터레이스의 사용이 끝났다면 WSACleanup 함수를 호출해야 한다. 윈속으로 하여금
윈속이 점유하고 있던 리소스를 해제하고 진행중이던 윈속 작업이 취소하게 된다.
int WSACleanup(void);
프로토콜의 주소 지정(ADRESSING a Protocol)
인터넷 프로토콜(IP , Internet Protocol) 을 이용하여 통신,
LAN (Local Area Network ) 과 WAN(Wide Area Network) 에서 사용되고 있다. 기본적으로 IP 자체적으로는 비연결형
프로토콜이며 완벽한 데이터 수신을 보장하지 않는다.
TCP(Transmission Control Protocol) 와 UDP (User Datagram Protocol) 가 통신 프로토콜로 주로 사용된다.
IPv4의 주소 지정
IPv4 에서는 32비트 주소를 사용.
클라이언트가 TCP 나 UDP 를 이용하여 서버와 통신하기를 원할때는 포트와 함께 IP 주소를 지정
서버가 클라이언트로 들어오는 요청을 수신하기 위해서도 IP 주소와 포트를 지정해야 한다.
윈속에서 IP 주소와 포트는 SOCKADDR_IN 구조체를 이용하여 지정
struct sockaddr_in
{
short sin_family; // IP 를 사용할 경우 반드시 AF_INET 으로 설정
u_short sin_port; // 통신하기를 원하는 서버측의 UDP 혹은 TCP 포트(FTP는 21번 , HTTP 80)
struct in_addr sin_addr; // 32비트의 unsigned long integer 타입. 상황에 따라 자신의 주소나 상대방의 주
// 소를 뜻함. IP 주소는 일밙거으로 인터넷 표준인 점으로 구분
char sin_zero[8]; // SOCKADDR_IN의 크기를 SOCKADDR 고 같은 크기로 만들기 위한 패딩 필드
}
unsigned long inet_addr(const char FAR* cp); // 점으로 구분된 주소를 32비트형 정수형으로 바꾸는 함수
바이트 순서(Byte Ordering)
big-endian 과 little-endian 으로 구분함
인텔 x86은 little-endian 을 따르며, 하위에서 상위의 순서로 바이트가 배열된다. ( 10진수 255를 2byte의 16진수로 나타내면 0xff, 0x00 이 된다. big-endian은 0x00, 0xff)
little-endian 의 경우는 우리가 이상적으로 사용하는 방향의 반대 방향
이렇게 컴퓨터 고유의 바이트 배열 순서를 호스트 바이트 오더(host-byte order) 라 한다.
IP 주소와 포트 번호와 여러 개의 바이트로 구성되면 컴퓨터에서는 고유한 호스트 바이트 오더에 따라 표시
네트웤에서는 IP 주소와 포트가 표시될 때는 네트웍 바이트 순서에 따라 표시
인터넷에서는 네트웤 바이트 오더를 big-endian 으로 정의
호스트 바이트 오더를 네트웤 바이트 오더로 변환해 주는 함수
u_long htonl(u_long hostlong); // 네트웤 바이트 오더로 된 숫자값으로 리턴한다. hostlong 은 호스트 바이트 오더형식의 4byte 숫자
int WSAHtonl(SOCKET s, u_long hostlong, u_long FAR* lpnetlong);
// lpnetlong 파라미터를 통하여 네트웤 바이트 오더로 된 숫자값을 리턴한다. hostshort 파라미터는 호스트 바이트 오더 형식의 2byte 숫자
u_short htons( u_short hostshort );
// 네트웤 바이트 오더로 된 숫자값을 리턴한다.
int WSAHtons( SOCKET s, u_short hostshort, u_short FAR* lpnetshort );
//lpnet-short 파라미터를 통하여 네트웍 바이트 오더로 된 숫자값을 리턴
네이웤 바이트 오더를 호스트 바이트오더로 바꿔주는 함수
int WSANtonhl( SOCKET s, u_long netlong, u_long FAR* lphostlong);
u_shot ntohs(u_short netshort);
int WSANtonhs( SOCKET s, u_short netshort, u_short FAR* lphostshort);
SOCKADDR_IN 을 이용한 IPv4 형식의 주소 지정 방법
SOCKADDR_IN InternetAddr;
INT nPortId = 5150;
InternetAddr.sin_family = AF_INET;
// 점으로 구분된 주소 136.149.3.29 를 4바이트의
// 숫자로 변환하고 sin_addr 에 입력
InternetAddr.sin_addr.s_addr = inte_addr("136.149.3.29");
// 호스트 바이트 순서(host-byte order)로 포트값이
// 저장되어 있는 변수 nPortId 를 네이웤 바이트 순서로 변환
InternetAddr.sin_port = htons(nPortId);
소켓 생성
SOCK2.H 의 SOCKET은 파일 디스크립터와 전혀 다른 형식으로 정의
SOCKET socket( int af, int type, int protocol );
af : 어드레스 패밀리를 의미하며 IPv4의 경우 AF_INET
type: 소켓 타입을 의미하는 것으로 , TCP/IP 기반 의 소켓을 생성하고자 한다면 SOCK_STREAM 을 UDP/IP 기반을 생성하고자 한다면 SOCK_DGRAM 으로 설정
protocol: 지정하는 필드로 동일한 어드레서 패밀리에 대하여 여러개의 프로토콜의 존재할 때 사용한다.
TCP 의 경우 IPROTO_TCP 를 UDP 의 경우 IPPROTO_UDP 를 사용
윈도우에서는 소켓의 옵션과 동작을 제어할 4개의 함수를 제공 : setsockopt, getsockopt , ioctlsocket, WSAIotcl 등
연결 지향 통신 ( Connection-Oriented Communication )
연결을 받고 연결을 시도하는 방법, 서버에서 어떻게 연결을 기다리고 연결을 수락하거나 거부하는 지,
클라이언트가 서버로 연결을 시도하는 과정을 알아본다. 어떻게 데이터를 주고 받는지도 배움
IP 에서 연결 지향 통신은 TCP/IP 를 통하여 이루어 진다. TCP 는 신뢰성 있는 데이터 전송을 제공한다.
응용 프로그램이 TCP 를 통하여 통신하면 두개의 지점간 가상 연결(virtual connection) 이 이루어지며 양방향으로
스트림 방식의 통신이 가능해진다.
서버측 API 함수들
WINSOCK SERVER
|
Socket()/WSASocket()
|
bind()
|
accept() WSAAceept()
서버는 클라이언트가 접속 가능한 주소로 연결을 기다림
TCP/IP 에서는 이러한 접속 가능한 주소로 서버의 네트웤 인터페이스의 IP 주소와 포트번호를 이용
바인딩(BINDING)
해당 프로토콜에 대한 소켓이 생성되면 클라이언트가 접속 가능한 소켓을 바인드 해야 한다.
BIND 함수는 이러한 일을 해주는 함수로 다음과 같이 정의되어 있다
int bind( SOCKET s, const struct sockaddr FAR* name, int namelen);
SOCKET s : 클라이언트의 연결을 기다릴 소켓
name : 구조체 sockaddr 의 포인터로 프로토콜에 해당하는 구조체에 값을 채운후 sockaddr의 포인터로 형변환하여 입력
namelen : 두번째 파라미터로 입력될 프로토콜의 구조체의 크기를 입력
연결대기(listening)
소켓을 연결 대기 상태로 놓는것. bind 함수는 단지 소켓에 주소를 할당하는 일만 했음
소켓이 연결을 기다릴수 있도록 하는 API 는 Listen
int Listen(SOCKET s, int backlog);
SOCKET s; // 바인드 된 소켓, 두번째 파라미터 backlog 는 들어오는 연결을 대기시킬 수 있는 최대 개수
연결수락(Accepting Connections)
연결 수락은 accept, WSAccept, AcceptEx의 호출을 통하여 이루어진다.
SOCKET accept( SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);
s는 연결 대기 모드에 있는 소켓.
'SYSTEM PROGRAMMING' 카테고리의 다른 글
TCP 를 구성하는 주요 알고리즘 (0) | 2015.08.05 |
---|---|
TCP 상태 변화 (0) | 2015.08.05 |
리눅스 쉘 (0) | 2015.08.05 |
리눅스 파일 시스템의 활용 (0) | 2015.08.05 |
서버 프로그래밍 (0) | 2015.08.05 |