프로토콜 : 대화에 필요한 통신 규약
두 사람이 대화하는데, 한 명은 전화로, 한 명은 편지로 대화하려 한다면 소통이 제대로 되지 못하듯, 통일된 방식으로 소통이 이루어져야한다. 통신 규약을 프로토콜 이라고 한다.
앞서 보았듯, socket()
함수를 통해 소켓을 만들었었다.
그렇다면 소켓은 어떻게 구성된 함수인지를 이해해보자.
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
// 성공 시 파일 디스크립터, 실패 시 -1
domain
: 소켓이 사용할 프로토콜 체계 정보type
: 소켓의 데이터 전송 타입protocol
: 두 컴퓨터 간 통신에 사용되는 프로토콜 정보name | Protocol Family |
---|---|
PF_INET | IPv4 인터넷 프로토콜 체계 |
PF_INET6 | IPv6 인터넷 프로토콜 체계 |
PF_LOCAL | 로컬 통신을 위한 UNIX 프로토콜 체계 |
PF_PACKET | Low level 소켓을 위한 프로토콜 체계 |
PF_IPX | IPX 노벨 프로토콜 체계 |
어떤 통신 체계를 사용하는지에 대해서 소켓의 첫 번째 인자로 전달해준다.
첫 번째 인자를 통해 정한 프로토콜 체계에서 세 번째 인자(프로토콜) 을 설정한다.
하나의 프로토콜 체계 내에는 여러 데이터 전송 방식이 존재함.
irc에서 다룰 IPv4 구조(PF_INET) 를 토대로 설명하면 다음과 같다.
신뢰성 있는 순차적 바이트 기반의 연결지향 데이터 전송 방식의 소켓.
socket()
함수의 두 번째 인자로 SOCK_STREAM
을 전달하면 연결지향형 소켓이 된다.
- 중간에 데이터가 소멸되지 않고 목적지로 전송
- 소켓 대 소켓의 연결이 반드시 1대1 연결이 되어야함.
- 전송 순서대로 데이터 수신
- 전송되는 데이터의 경계(Boundary)가 존재하지 않음
위 특징 중 마지막의 경우 이와 같은 상황이다.
"사탕 100개가 총 5번에 걸쳐 보내졌다. 하지만 받는 사람은 사탕 100개를 쌓아서 한 번에 봉지에 담아갔다."
이는 곧, 5번의 write()
를 통해 100 바이트를 전송했으나, 데이터를 수신하는 컴퓨터는 1 번의 read()
로 100 바이트를 수신했다는 비유로 볼 수 있다.
소켓 내부적으로 버퍼가 존재한다. 송수신되는 데이터가 이 버퍼에 우선 저장되는데, 만약 버퍼가 가득 차게되면 데이터가 담기지 못하는 "데이터 손실" 이 발생할 것이라고 생각할 수 있다.
하지만 연결지항형 소켓
의 경우 상태 소켓의 상태를 파악해가며 데이터 송수신이 이뤄진다. 상대의 버퍼가 가득차면 보내기를 중지하고, 심지어는 잘 보내지지 않았을 경우 재전송하기도 한다.
즉, 연결지향형 소켓
은 특별한 경우가 아니면 데이터손실이 발생하지 않는다.
신뢰성과 순차적 데이터 전송을 보장하지 않는, 고속의 데이터 전송을 목적으로 하는 소켓.
- 전송 순서 상관없이 가장 빠른 전송 지향
- 전송 데이터에 손실의 우려가 있음.
- 전송 데이터의 경계(Boundary) 존재.
- 한번에 전송할 수 있는 데이터 크기에 제한 존재.
퀵 택배를 생각하면 좋다.
하나의 큰 기계를 분해하여 열 파트로 분리했다고 하고, 각 파트를 퀵으로 보내자.
각각이 오토바이에 실려서 목적지로 전달되는데, 위험하다보니 파손될 수 있고, 오토바이 적재량에 따라 보낼 수 있는 한계가 존재한다. 또한 열 개의 파트로 분리해서 열 개의 퀵으로 보냈으니 받는 사람도 열 번 받게된다.
각 오토바이가 다른 길로 올수도 있다보니 나중에 보낸 것이 먼저 오기도 한다.
이러한 특징을 지닌 타입을 비 연결지향형 소켓
이라고 한다.
socket()
함수의 세 번째 인자.
근데 앞서 프로토콜 체계 정보(첫 번째 인자), 전송 타입(두 번째 인자)를 전달했는데 프로토콜이 확정되지 않을 수가 있나?
앞서 전달한 인자들만으로 프로토콜이 경우도 존재하기 때문에, 세 번째 인자는 0
으로 전달하더라도 소켓이 생성될 수 있다.
하지만 프로토콜 체계 내의 하나의 전송 타입에도 여러 가지 프로토콜이 존재할 수 있기 때문에 세 번째 인자가 존재하는 것이다.
// IPv4 인터넷 프로토콜 체계(PF) 에서 동작하는 연결 지향형 데이터 전송(type) 소켓
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// IPv4 인터넷 프로토콜 체계(PF) 에서 동작하는 비 연결 지향형 데이터 전송(type) 소켓
int udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
IPv4 인터넷 프로토콜 체계(PF) 에서 동작하는 연결 지향형 / 비연결 지향형 각각 하나씩 존재하는데, 연결 지향형을 TCP 소켓
, 비 연결지향형을 UDP 소켓
이라고 한다.