네트워크 프로그래밍과 소켓의 이해


1. 네트워크 프로그래밍의 이해


네트워크 프로그래밍이란?

멀리 떨어져 있는 호스트들이 서로 데이터를 주고 받을 수 있도록 프로그램을 구현하는 것이다. 파일과 달리 데이터를 주고 받을 대상이 멀리 떨어져 있기 때문에 소프트웨어 차원에서 호스트들간에 연결을 해주는 장치가 필요하다. 이러한 기능을 해주는 장치를 소켓(socket)이라 한다. 일반적으로 소켓 프로그래밍이라는 용어와 네트워크 프로그래밍이라는 용어는 같은 의미로 사용되고 있다.



2. 소켓 이해하기


1. 서버 소켓 구현의 이해

소켓이란 멀리 떨어져 있는 두개의 호스트(host)를 연결시켜 주는 매개체 역할을 한다. 네트워크 프로그래밍에서 소켓이 필요한 이유는 바로 그것이다.


다음은 소켓을 생성하는 함수 선언이다.

#include <sys/types.h>
#include <sys/socket.h>

// 성공시 파일 디스크립터, 실패 시 -1 리턴
int socket(int domain, int type, int protocol);


전화기에 전화번호를 할당하는 것처럼, 소켓에도 전화번호에 해당하는 소켓의  IP 주소를 할당해야 한다.

다음은 소켓에 주소를 할당하는 함수의 선언이다.

#include <sys/socket.h>

// 성공시 0, 실패 시 -1 리턴
int bind(int sockfd, struct  sockaddr *myaddr, int addrlen);


소켓이 연결 요청이 가능한 상태가 되어야 한다.

다음 함수는 소켓을 연결 요청이 가능한 상태가 되게 한다.

#include <sys/socket.h>

// 성공시 0, 실패 시 -1 리턴
int  listen(int sockfd, int backlog);


누군가 데이터를 주고 받기 위해 연결 요청을 해 오면, 그 요청을 수락할 수 있어야 한다.

다음은 요청을 수락하는 함수이다.

#include <sys/socket.h>

// 성공시 파일 디스크립터, 실패 시 -1 리턴
int accept(int sockfd, struct sockaddr *addr, int *addrlen);



3. 윈도우즈 기반으로 구현하기


1. 윈도우즈 소켓을 위한 헤더와 라이브러리 설정하기

윈속2를 기반으로 프로그램을 개발하기 위해서는 반드시 winsock2.h 헤더를 포함해야 한다. 또한 winsock2.h 헤더를 포함하기 위해서는 ws2_32.lib 라이브러리를 링크시켜야 한다.



2. 윈속 초기화 하기

윈속 프로그래밍을 할 때 반디스 WSAStartup 함수를 호출해 줘야 한다. 이 함수를 호출하는 목적은 프로그램에서 요구하는 윈속의 버전을 알려줘, 해당 버전의 윈속 사용을 위한 라이브러리 초기화 작업을 진행하기 위한 것이다.

#include <winsock2.h>

// 성공 시 0, 실패 시 0이 아닌 에러 코드 리턴
int WSAStartup(
	WORD wVersionRequested,
	LPWSADATA lpWSAData
);


- wVersionRequested : 프로그램에서 요구하는 윈속의 최상위 버전을 알려주기 위해 사용된다. WORD는 16비트 unsigned int를 의미하며, 상위 8비트는 부 버전, 하위 8비트는 주 버전을 표시해 준다. MAKEWORD 함수(매크로 함수)가 제공되며 이 함수를 사용하면 원하는 WORD값을 쉽게 만들 수 있다.

- lpWSAData : WSADATA타입 변수의 포인터를 인자로 전달한다. 함수 호출이 끝나면 WSADATA 변수에는 로딩한 DLL에 대한 정보가 채워진다.

#include <winsock2.h>

WORD  MAKEWORD(
	BYTE bLow,
	BYTE bHigh
);

MAKEWORD는 매크로 함수로 원하는 WORD값을 만들어 준다. 



초기화를 해 주었다면, 종료 시에는 그에 따른 적절한 처리도 해 줘야 한다. WSACleanup 함수 호출을 통해서 할당 받은 리소스를 해제하는 작업을 해야 한다.

#include <winsock2.h>

// 성공 시 0, 실패 시 SOCKET_ERROR 리턴
int WSACleanup(void);



3. 윈속 기반의 소켓 관련 함수


■ 소켓의 생성

#include <winsock2.h>

// 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET 리턴
SOCKET socket(int af, int type, int protocol);


■ 주소와 Port 할당

#include <winsock2.h>

// 성공 시 0, 실패 시 SOCKET_ERROR 리턴
int bind(SOCKET s, const sturct sockaddr FAR *name, int namelen);


■ '연결 요청 대기 상태'로의 진입

#include <winsock2.h>

// 성공 시 0, 실패 시 SOCKET_ERROR 리턴
int listen(SOCKET s, int backlog);


■ 연결 수락

#include <winsock2.h>

// 성공 시 소켓 핸들, 실패 시 INVALID_SOCKET
SOCKET accept(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen);


■ 연결 요청

#include <winsock2.h>

// 성공 시 0, 실패 시 SOCKET_ERROR 리턴
int connect(SOCKET s, const struct sockaddr FAR *name, int namelen);



4. 윈속 기반의 데이터 입출력 함수

#include <winsock2.h>

// 성공 시 전송한 바이트 수, 실패 시 SOCKET_ERROR 리턴
int send(SOCKET s, const char FAR *buf, int len, int flags);

- s : 데이터를 전송할 호스트에 연결된 소켓의 핸들을 인자로 전달한다.

- buf : 전송할 데이터를 저장하고 있는 버퍼를 가르키는 포인터이다.

- len : 전송할 바이트 수를 인자로 전달한다.

- flags : 함수 호출 시, 여러 가지 옵션을 설정하기 위해서 사용된다.



#include <winsock2.h>

// 성공 시 수신한 바이트 수(단 EOF 전송시 0), 실패 시 SOCKET_ERROR 리턴
int recv(SOCKET s, char FAR *buf, int len, int flags);

- s : 데이터를 수신할 영역을 나타내는 소켓의 핸들이다.

- buf : 수신할 데이터를 저장할 버퍼를 가르키는 포인터이다.

- len : 수신할 최대 바이트 수이다.

- flags : 함수 호출 시, 여러가지 옵션을 설정하기 위해서 사용된다.










posted by deviAk