이 시리즈에서 구현하는 웹 서버는 유닉스 OS에서 동작한다고 가정한다.
소켓을 생성하는 함수인 socket 함수의 프로토타입은 아래와 같다.
#include <sys/socket.h>
int socket(int domain, int type, int protocol); // 성공 시 파일 디스크립터, 실패시 -1 반환
비슷한 프로토콜을 묶어서 프로토콜 체계라 부른다. 필자는 프로토콜 체계를 나누는 기준이 무엇인지 파악하지 않았다. 웹 서버를 구현하는데 있어, 이 기준을 파악하는게 중요하다고 판단하지 않았기 때문이다. sys/socket.h 헤더에 정의된 프로토콜 체계는 아래와 같다.
이름 | 프로토콜 체계(Protocol Family) |
---|---|
PF_INET | IPv4 인터넷 프로토콜 체계 |
PF_INET6 | IPv6 인터넷 프로토콜 체계 |
PF_LOCAL | 로컬 통신을 위한 UNIX 프로토콜 체계 |
PF_PACKET | Low Level 소켓을 위한 프로토콜 체계 |
PF_IPX | IPX 노벨 프로토콜 체계 |
TCP를 기반으로 HTTP를 구현할 것이기 때문에 필자가 사용한 프로토콜 체계는 IPv4 인터넷 프로토콜 체계다. 그렇기에 socket을 생성할 때, 첫 번째 인자인 domain에 PF_INET을 입력하면 된다.
프로토콜 체계는 여러 종류의 프로토콜로 구성된다. 한 프로토콜 체계에서 프로토콜의 연결성을 기준으로 프로토콜을 분류할 수 있다.
연결지향형 소켓은 아래와 같은 성질을 갖는다.
1 번과 2 번은 직관적이다. 3 번 성질이 무슨 의미를 갖는지 아리송한데, buffer를 read한 횟수와 write한 횟수가 일치하지 않아도 된다는 의미이다. 서버가 99 바이트의 데이터를 작성한 뒤 클라이언트가 33 바이트씩 3 번 읽어도 무방하다는 의미다.
전송되는 데이터의 경계가 존재하기 때문에, read한 횟수와 write한 횟수가 일치해야한다.
TCP는 연결지향형 프로토콜이기 때문에, socket 함수의 두 번째 인자로 SOCK_STREAM을 전달해야 한다.
사실 IPv4 인터넷 프로토콜 체계에서 연결지향형 프로토콜은 TCP밖에 없기에 세 번째 인자가 왜 필요한지 의문이 들 수 있다. 이는 특수한 경우이고 프로토콜 체계에서 연결지향형 프로토콜이 2 개 이상 존재할 수 있기에 세 번째 인자가 필요하다. TCP처럼 세 번째 인자가 필요하지 않은 경우라면 0을 전달하면 된다.
윤성우 저 열혈강의 TCP/IP 소켓 프로그래밍