소켓의 생성과 프로토콜의 설정


1. 프로토콜의 정의


프로토콜이란 '컴퓨터 상호간의 대화에 필요한 통신 규약'을 의미 한다. 그러나 네트워크 프로그래밍에서 프로토콜이란 용어는 조금 더 다양하게 사용된다. 



2. 소켓의 생성


소켓을 생성하기 위해서 리눅스 윈도우즈 공통으로 socket이란 함수를 사용하게 된다. socket 함수는 호출 시 시스템 내부적으로 소켓을 생성하고 그 소켓을 조작하기 위해 필요한 파일 디스크립터를 리턴하는 함수이다.


시스템 내부적으로 소켓을 생성한다는 의미는 호스트가 통신을 하기 위해 필요한 리소스를 할당하는 것을 의미한다.

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

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

- domain : 생성할 소켓이 통신 하기 위해ㅔ 사용할 프로토콜 체계(Protocol Family)를 설정한다.

- type : 소켓이 데이터를 전송하는데 있어서, 사용하게 되는 전송 타입을 설정해 준다.

- protocol : 두 호스트간에 통신을 하는데 있어서 특정 프로토콜을 지정 하기위해 사용된다.



3. 프로토콜 체계(Protocol Family)


sys/socket.h에 선언되어 있는 프로토콜 체계

프로토콜 체계(Protocol Family)

정의

 PF_INET

 IPv4 인터넷 프로토콜 

 PF_INET6

 IPv6 인터넷 프로토콜

 PF_LOCAL

 Local 통신을 위한 UNIX 프로토콜

 PF_PACKET

 Low Level socket을 위한 인터페이스

 PF_IPX

 IPX 노벨 프로토콜



4. 소켓의 타입


socket 함수의 두 번쨰 인자로 소켓의 타입을 설정해야 한다. 여기서 의미하는 타입이란 데이터 전송 타입을 말하는 것이다. 하나의 프로토콜 체계 안에서도 데이터를 전송하는 방법이 둘 이상 존재할 수 있다.


1. SOCK_STREAM

SOCK_STREAM 타입으로 설정하면 소켓은 연결 지향형 소켓이 된다. 


- 에러나 데이터의 손실 없이 무사히 전달된다.

 독립된 전송 라인을 통하여 데이터를 전달하기 때문에 라인상에 문제만 없다면, 데이터가 반드시 전달된다는 것을 보장받을 수 있다. 또한 하나의 라인이 존재한다는 것은 반디스 호스트 대 호스트의 연결은 1:1이어야 한다는 것을 의미한다.


- 전송하는 순서대로 데이터가 전달된다.

 전송 라인이 하나이기 때문에 뒤에 보낸 데이터가 이전에 보낸 데이터보다 일찍 도착할 수는 없을 것이다. 따라서 데이터를 전송하는 호스트는 순서대로 데이터가 전송된다는 믿음을 가질 수 있다.


- 전송되는 데이터의 경계(Boundary)가 존재하지 않는다.

 호스트 대 호스트가 연결 지향 소켓을 생성해서 통신을 하는 경우, 두 번의 write 함수 호출을 통해서 데이터를 전송했다 하더라도, 수신측 호스트의 버퍼가 넉넉하다면 한번의 read 함수 호출을 통해서 모든 데이터를 수신할 수 있다. 또한 반대로 한번의 write 함수 호출을 통해서 데이터가 전송되었다 하더라도, 서너 번의 read 함수 호출을 통해서 데이터를 조금씩 나누어 수신할 수도 있다.

 이러한 특성을 두고, 전송되는 데이터의 경계가 존재하지 않는다고 표현한다.


SOCK_STREAM의 특징은 "신뢰성 있는 순차적인 바이트 기반의 연결 지향 전송 타입"이라 말할 수 있다.



2. SOCK_DGRAM

SOCK_DGRAM 타입으로 설정하면 소켓은 비연결 지향형 소켓이 된다. 


- 전송되는 순서에 상관없이 가장 빠른 전송을 지향한다.

 출발한 순서가 크게 차이나지 않는 한, 어떤 데이터가 먼저 도착할 지에 대한 예측은 불가능하다. 오로지 빠른 시간 내에 전송 하려고 최선의 노력을 다한다는 믿은만 있을 뿐이다.


- 전송되는 데이터는 손실될 수도 있고 에러가 발생할 수도 있다.

 데이터가 빠르게 전달되지만 경우에 따라서는 손상되거나 잃어버릴 수도 있다.


- 전송되는 데이터의 경계(Boundary)가 존재한다.

 데이터를 전송하는 호스트가 세 번의 함수 호출을 통해서 데이터를 전송했다면, 수신하는 호스트도 반드시 세 번의 함수 호출을 거쳐야 데이터를 완전히 수신할 수 있게 된다. 데이터의 경계가 없었던 SOCK_STREAM타입과는 대조를 이룬다.


- 한번에 전송되는 데이터의 크기는 제한된다.

비연결 지향형 소켓을 기반으로 데이터를 전송할 경우 호스트가 한번에 전송하는 데이터의 크기는 제한될 수 밖에 없다. 따라서 그 크기가 크다면 적절히 데이터를 나누어야 한다.


비 연결 지향형 소켓의 경우 빠른 전송을 위해 최선을 다하지만, 경우에 따라서는 데이터의 손실이 있을 수도 있으며, 전송되는 데이터의 크기가 제한되어 있기 때문에 덩치가 큰 데이터를 전송할 경우 나누어서 보내야 한다.



5. 프로토콜의 선택


socket 함수의 세 번째 전달되는 인자는 호스트 대 호스트가 사용할 프로토콜을 설정하기 위해 사용된다.


프로토콜 체계가 PF_INET인 경우 다음과 같은 값이 올 수 있다.


- IPPROTO_TCP : TCP를 기반으로 하는 소켓을 생성

- IPPROTO_UDP : UDP를 기반으로 하는 소켓을 생성


TCP 소켓이란 인터넷을 기반으로 하는 연결 지향형 소켓을 의미한다. 또한 UDP 소켓이란 인터넷을 기반으로 하는 비연결 지향형 소켓을 의미한다. 



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


socket 함수는 윈도우즈 기반으로 변경하더라도 큰 차이점은 보이지 않는다.

#include <winsock2.h>

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




posted by deviAk