Published on

TCP/UDP multiplexing : 네트워크-12

Overview

"철수네 집에 사는 12명의 아이들이 영희네 사는 12명의 아이들에게 편지를 보냅니다."

이 문장을 네트워크 구조로 바꾸어볼까요?

"A 호스트의 12 프로세스가 B 호스트의 12 프로세스에게 메세지를 전송합니다."

즉, 집 = Host, 아이들 = Process, 편지 = message로 볼 수 있습니다.

이 때 network layer는 철수네 집에서 영희네 집까지 메세지의 전송을 책임집니다.

transport layer는 철수네 집 첫 번째 아이가 보낸 편지를 영희네 집 첫째가 무사히 받을 수 있도록 하는 역할을 수행합니다.

이 때 transport layer와

이제 이러한 역할을 수행하는 프로토콜은 크게 2개, TCP/UDP가 존재하는데요.

TCP와 UDP의 가장 큰 차이는 Connection의 유무입니다.

TCP는 Connection을 수행하는 반면 UDP는 Connection을 수행하지 않는데요.

이번엔 두 프로토콜이 어떤 식으로 multiplexing, demultiplexing에 차이가 생기는지 알아보도록 하겠습니다.

Socket

TCP/UDP에 상관없이 전송계층에선 각 호스트가 통신을 위해 프로세스를 위한 소켓(Socket)을 생성합니다.

소켓은 전송계층과 어플리케이션(혹은 상위계층 프로토콜)이 데이터를 주고받을 인터페이스입니다.

보통 소켓까지가 운영체제에서 구현되는 부분으로 상위 계층(http, ssh, ftp 등)의 통신은 소켓을 이용해 라이브러리 혹은 유저 프로그램으로 구현됩니다.

이 소켓의 생성은 현재 프로세스와 1대1(혹은 프로세스:소켓=1:M)로 매칭되어 프로세스는 소켓을 위해 생성할 포트를 지정해야만 합니다.

이제 이 소켓을 UDP와 TCP가 어떻게 이용하고 통신하는지 살펴보겠습니다.

Connectionless Demultiplexing

우선 UDP 데이터그램이 전송될 때를 살펴보겠습니다.
UDP는 연결을 맺지 않기 때문에 소켓은 현재 호스트와 프로세스에 대한 정보만을 알고 있으면 됩니다.

호스트와 프로세스는 운영체제에서 식별하기 때문에 어플리케이션은 프로세스에 지정될 포트 번호만 지정합니다.

DatagramSocket socket = new DatagramSocket(12345);
// 0~1023은 well-known 포트임으로 피해주는 것이 좋습니다.

데이터를 보낼 때는 목적지의 호스트와 포트를 지정하는 것으로 충분합니다.

DatagramPacket packet = new DatagramPacket(buffer, length, /** 목적지 호스트 주소*/address, /** 목적지 프로세스 포트*/port);

socket.send(packet);

따라서 만약 서버-클라이언트 모델에서 UDP 소켓을 사용한다면, 각 클라이언트와 서버마다 하나씩의 소켓만 보유하게 됩니다.

alt text

이제 각 호스트는 들어온 패킷의 목적지 포트를 보고 해당 프로세스에 데이터를 분배(demultiplex)해주는 것으로 충분합니다.

Connection-Oriented Demultiplexing

TCP는 연결지향으로 UDP와 소켓의 전략이 조금 달라집니다.

다시 서버-클라이언트 모델을 떠올려봅시다.

서버와 클라이언트는 1대 다수의 관계로 구성되는데요.

만약 서버에 하나의 소켓만 있다면 어떻게 될까요?

해당 소켓이 어떤 클라이언트 A와 연결되면, 다른 클라이언트 B는 연결을 시도할 경우, B는 A의 연결이 종료되기를 기다려야 할 겁니다.

수많은 트래픽을 감당해야하는 서버가 만약 이렇게 동작할 경우 엄청난 병목이 발생할 겁니다.

따라서 서버는 각 클라이언트를 위한 소켓을 따로 생성하는 것이 합리적일 것 입니다.

따라서 TCP 소켓은 현재 호스트, 포트에 대한 정보 뿐만 아니라 목적지 호스트와 포트에 대한 정보도 함께 저장하여 식별됩니다.

흔히 웹브라우저 등을 사용할 경우를 예로 들면 만약 다른 두 개의 창에서 똑같은 사이트에 접속할 경우 서버에선 두 개의 창마다 각각 소켓을 생성하게 됩니다.

alt text

이 때 각 소켓마다 새로운 thread를 생성하여 클라이언트를 관리하는 경우도 있고, 자바스크립트와 같이 이벤트루프를 이용해 비동기적인 처리를 할 수도 있습니다.