소켓의 프로토콜 체계를 결정한 후에는, 해당 프로토콜 체계 내에서 어떠한 방식으로 데이터를 전송할 것인지 결정해야 한다. 예를 들어서 PF_INET에 해당하는 프로토콜 체계에는 둘 이상의 데이터 전송방식이 존재한다.
연결지향형 소켓(SOCK_STREAM)
연결 지향형 소켓은 TCP 방식으로 연결을 지원하며 특징은 아래와 같다.
- 중간에 데이터가 소멸되지 않고 목적지로 전송된다.
- 전송 순서대로 데이터가 수신된다.
- 전송되는 데이터의 경계(Boundary)가 존재하지 않는다(중요)
- 소켓 대 소켓의 연결은 반드시 1대 1이어야 한다.
1, 2번의 특성은 우리가 익히 알던 TCP의 특성이다. 그리고 4번은 그리 이해하기 어렵지 않다. 그러므로 3번에 대해 좀 더 자세히 알아보자.
데이터를 송수신하는 소켓은 내부적으로 버퍼(buffer), 쉽게 말해서 바이트 배열을 지니고 있다. 그리고 소켓을 통해 전송되는 데이터는 일단 이 배열에 저장된다. 때문에 데이터가 수신되었다고 해서 바로 read()를 통해 호출해야 하는 것은 아니다. 버퍼의 용량을 초과하지 않는 한, 여러 번에 걸쳐 데이터가 채워진 후에 한 번의 read() 호출을 통해서 데이터 전부를 읽어 들일수도 있고, 반대로 한번의 write() 호출로 전송된 데이터를 여러 번의 read() 호출을 통해 읽어들일 수도 있다. 즉, read()의 호출횟수와 write() 함수의 호출횟수는 연결지향형 소켓의 경우 큰 의미를 갖지 못한다. 때문에 연결지향형 소켓은 데이터의 경계가 존재하지 않는다고 말하는 것이다.
비 연결지향형 소켓(SOCK_DGRAM)
- 전송된 순서에 상관없이 가장 빠른 전송을 지향한다.
- 전송된 데이터는 손실의 우려가 있고, 파손의 우려가 있다.
- 전송되는 데이터의 경계(Boundary)가 존재한다.
- 한 번에 전송할 수 있는 데이터의 크기가 제한된다.
- 연결이라는 개념이 존재하지 않는다.
마찬가지로 1, 2번의 특성은 우리가 익히 알던 UDP의 그것이다. 3,4 번은 연결지향형 소켓과 반대의 특성을 지니고 있다. 전송되는 데이터의 경계가 존재한다는 것은 아래와 같은 의미를 가진다.
- 연결지향형 소켓의 경우, 첫 번째 write()로 50 byte의 데이터를 송신하고 두 번째 write()로 50 byte의 데이터를 송신한 후에, 한 번에 read()만으로 100 byte의 데이터를 한꺼번에 수신할 수 있다.
- 반면에, 비연결지향형 소켓의 경우 두 번의 read()를 사용하여 데이터를 50 byte 씩 나눠서 수신해야 한다. 데이터의 경계가 정해져 있기 때문이다.
4, 5번 특성에 대해서는 차후 부연한다.
socket()의 세번째 인자, protocol에 대하여
socket 시스템콜에는 protocol이라는 세번째 인자가 존재한다.
첫번째 인자로 프로토콜 체계를 정의하고, 두번째 인자로 소켓의 타입을 지정하였으므로 이미 프로토콜 결정에 충분한 정보를 전달하였다고 판단할 수 있다. 하지만 다음과 같은 상황 때문에 세번째 인자는 필요하다.
하나의 프로토콜 체계 안에 데이터의 전송방식이 동일한 프로토콜이 둘 이상 존재하는 경우
예를 들어 첫번째 인자로 PF_INET을 넘기고, 두번째 인자로 SOCK_STREAM을 넘기는 것은 다음을 의미한다.
IPv4 인터넷 프로토콜 체계에서 동작하는 연결지향형 데이터 전송 소켓
위 조건을 충족하는 프로토콜은 IPPROTO_TCP 하나이기 때문에 세번째 인자로 0을 전달하여도 정상적으로 소켓은 생성된다. 하지만 좀 더 명시적으로 코드를 작성하고 싶다면 아래와 같이 작성하면 된다. 아래와 같이 생성되는 소켓을 가리켜 TCP 소켓이라 한다.
int tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);UDP 소켓은 아래와 같은 정의를 가지고 있다.
IPv4 인터넷 프로토콜 체계에서 동작하는 비 연결지향형 데이터 전송 소켓
위 조건을 만족하는 프로토콜은 IPPROTO_UDP 하나이기 때문에 세번째 인자로 0을 전달하여도 되고, 명시적으로 인자를 전달하여도 된다.
int udp_socket = socket(PF_INET , SOCK_DGRAM, IPPROTO_UDP);참고자료