본문 바로가기

Dev.Basic/네트워크

#Transport Layer, TCP vs UDP

#Transport Layer, TCP vs UDP

인터넷은 트랜스포츠 계층에 연결형 프로토콜과 비연결형 프로토콜, 이렇게 두 개의 주된 프로토콜을 갖는다.

UDP
UDP(User Datagram Protocol, 사용자 데이터그램 프로토콜)는 비연결형 프로토콜이다. IP 데이터그램을 캡슐화하여 보내는 방법과 연결 설정을 하지 않고 보내는 방법을 제공한다. UDP는 흐름제어, 오류제어 또는 손상된 세그먼트의 수신에 대한 재전송을 하지 않는다. 이 모두가 사용자 프로세스의 몫이다. UDP가 행하는 것은 포트들을 사용하여 IP 프로토콜에 인터페이스를 제공하는 것이다.

UDP가 특별히 유용한 분야는 클라이언트-서버 상황이다. 종종 클라이언트는 서버로 짧은 요청을 보내고, 짧은 응답을 기대한다.
만약 요청 또는 응답이 손실된다면, 클라이언트는 time out되고 다시 시도할 수 있다. 코드가 간단할 뿐만 아니라 TCP처럼 초기설정(initial setup)에서 요구되는 프로토콜에서보다 적은 메시지가 요구된다.

UDP를 사용한 것들에는 DNS가 있다. 어떤 호스트 네임의 IP 주소를 찾을 필요가 있는 프로그램은, DNS서버로 호스트 네임을 포함한 UDP 패킷을 보낸다. 이 서버는 호스트의 IP  주소를 포함한 UDP 패킷으로 응답한다. 사전에 설정이 필요하지 않으며 그 후에 해제가 필요하지 않다.

UDP가 사용되는 또 다른 분야로 실시간 멀티미디어가 있다. 실시간 멀티미디어의 응용이 많아지면서 오디오와 비디오 데이터 패킷 형식으로 전송하는 실시간 트랜스포트 프로토콜(RTP : Real-time Transport Protocol)이 탄생했다. RTP의 기본 기능은 UDP 패킷의 단일 스트림으로 몇몇 실시간 데이터 스트림을 멀티플렉싱하는 것이다. UDP 스트림은 단일 목적지 또는 다중 목적지들로 전송될 수 있다. RTP는 단지 일반적인 UDP를 사용하기 때문에 전달, 지연, 손실 등에 대한 특별한 보장이 없다.

이런 점들을 보완하기 위한 몇 가지 장치들이 존재한다. RTP 스트림에서 보내지는 각 패킷은 바로 전 패킷보다 하나 높은 번호가 주어진다. 이런 번호 부여 방식은 목적지로 하여금 어느 패킷이 분실됐는지 알 수 있게 한다. 만약 한 패킷이 없다면 이를 획득하기 위해 목적지에서의 최상의 동작은 보간(Interpolation)에 의해 손실한 값에 대한 근사치를 얻는 것이다. 재전송은 재전송된 패킷이 유용하기에 너무 늦게 도착하므로 실용적인 옵션이 아니다. 그러므로 RTP는 확인 응답이 없고 재전송을 요청하는 매커니즘도 없다.



TCP
대부분의 인터넷 응용분야들은 신뢰성과 순차적인 전달을 필요로 한다. UDP로는 이를 만족시킬 수 없으므로 다른 프로토콜이 필요하여 탄생한 것이 TCP이다.

TCP(Transmission Control Protocl, 전송제어 프로토콜)는 신뢰성이 없는 인터넷을 통해 종단간에 신뢰성 있는 바이트 스트림을 전송하도록 특별히 설계되었다. TCP 서비스는 송신자와 수신자 모두가 소켓이라고 부르는 종단점을 생성함으로써 이루어진다. 각 소켓은 호스트의 IP주소와 그 호스트에 국한된 16비트로 구성된 포트라고 불리는 소켓 번호를 갖는다. TCP 서비스를 하기 위해서는 송신측 소켓과 수신측 소켓이 연결되어 있어야 한다.

모든 TCP 연결은 전이중(full-duplex), 점대점(point to point)방식이다. 전이중이란 전송이 양방향으로 동시에 일어날 수 있음을 의미하며 점대점이란 각 연결이 정확히 2개의 종단점을 가지고 있음을 의미한다. TCP는 멀티캐스팅이나 브로드캐스팅을 지원하지 않는다. 또한 메시지 스트림이 아니라 바이트 스트림의 형태를 갖는다. 메시지의 시작에서 끝까지의 경계가 유지되지 않는다.

TCP의 특징은 TCP 연결상의 모든 바이트가 고유의 32-비트 순서번호(sequence number)를 갖는다는 것이다. 송수신 TCP 개체들은 세그먼트의 형태로서 데이터를 주고받는다. 한 세그먼트는 고정 2바이트 헤더와 그 뒤를 따르는 0개 이상의 데이터 바이트들로 구성된다. TCP 소프트웨어는 세그먼트가 얼마나 커야 하는지를 결정한다. 세그먼트 크기에는 두 가지 제약요소가 있다. 한 가지는 모든 세그먼트들은 TCP 헤더를 포함하여 IP 수용량인 65,515바이트를 넘을 수 없다는 것이며 나머지 하나는 모든 네트워크는 정해진 MTU(Maximum transfer Unit, 최대 전송 단위)를 갖는데 각 세그먼트는 이 MTU를 넘을 수 없다는 것이다.

TCP 개체들에 의해 사용되는 기본 프로토콜은 동적으로 윈도우 크기를 조절하는 슬라이딩 윈도우(sliding window)프로토콜이다. 송신자는 한 세그먼트를 전송할 때, 타이머를 구동시킨다 그 세그먼트가 목적지에 도달하면, 수신측 TCP 개체는 다음에 받으려고 하는 순서번호와 같은 확인 응답 번호를 포함하는 세그먼트를 송신측으로 보낸다. 보낼 데이터가 있다면 그 데이터와 함께 보낸다.
만일 확인 응답의 수신 전에 보낼 때 구동시킨 타이머가 종료되면 송신자는 그 세그먼트를 재전송한다. 세그먼트들이 순서가 뒤바뀐 상태로 도착할 수 있으며, 재전송 경우에 대해 올바르게 수신된 상태인지를 알 수 있도록 장치가 필요하다. 스트림 내의 각 바이트가 자기 고유의 offset을 가지고 있는 것을 그 장치로 한다.

TCP에서 연결 설정(connection establishment)는 3-way-handshake를 통해 행해진다. 하나의 연결을 설정하려면 한쪽(서버)은 listen과 accept를 실행함으로써 연결 요청을 수동적으로 기다린다. 이 listen와 accept는 특정 근원지를 명시할 수도 있고 하지 않을 수도 있다. 다른 한 쪽(client)은 connect를 실행하고 목적지 IP 주소와 포트, 수신 가능한 최대 TCP 세그먼트 크기 그리고 기타 사용자 데이터를 명시한다.

TCP에서 흐름제어는 가변크기의 슬라이딩 윈도우를 사용하여 처리된다. window size 필드는 확인 응답된 바이트에서 시작하여 얼마나 많은 바이트가 보내질 수 있는지를 나타낸다. 그러나 이 경우 좋지 않은 상황이 발생할 수 있다. 송신자는 응용프로그램에서 데이터가 올 때마다 전송할 필요가 없고 수신자도 맘찬가지로 데이터를 받은 즉시 확인 응답을 해야 하는 것이 아니다. 버퍼를 사용하면 되기 때문에 데이터를 모아서 보내거나 그것을 받고 애플리케이션에게 모아서 전달할 수 있는 것이다.

각 키보드 입력마다 즉시 반응해야 하는 '인터렉티브 에디터(Interactive Editor)'라면 어떨까?
송신측에서 한 번에 1바이트씩 데이터를 전송해오는 것이다. 이러한 상황을 해결하기 위해 지연 확인 응답(delayed acknowledgement)방법을 사용한다. 응답 메시지를 전송하는 것과 윈도우 사이즈를 갱신하는 것을 지연시키는 것이다. 하지만 이 방법이 네트워크 부하를 감소시켜준다고 할 지라도 송신측에서는 계속해서 1바이트씩 보내게 된다.

그래서 네이글 알고리즘(Nagle Algorithm)을 통해 해결하곤 한다. 데이터가 한 번에 한 바이트씩 송신자에게 올 경우, 첫번째 바이트만을 송신하고 나머지는 보낸 바이트에 대한 명백한 확인 응답이 올 때 까지 버퍼에 보관한다는 것이다. 그리고 버퍼 내의 모든 문자를 하나의 TCP 세그먼트로서 전송한 후, 또 응답 메시지가 도착할 때까지 버퍼에 전송할 데이터를 저장한다. 하지만 이 알고리즘이 교착상태를 야기할 수 있고 그 결과 웹 페이지의 다운을 초래할 수 있다.

그런데 애플리케이션이 수신된 데이터를 1바이트씩 가져간다면 어떻게 될까?
수신측은 버퍼에서 1바이트가 비었기 때문에 window size를 1바이트로 설정해서 응답을 하게 되고 송신측은 window size가 1바이트니 1바이트만큼의 데이터를 전송하게 된다. 1바이트의 데이터를 보내기 위해 41바이트의 패킷 구성을 하는 비효율적인 상황이 발생하게 된다. 이런 상황을 silly window syndrome이라고 하는데, 이 상황을 최적화 하기 위해 1바이트에 해당하는 윈도우 사이즈를 통보하지 않는다. 설정 당시 통보한 세그먼트의 최대 크기를 처리할 수 있게 되거나, 버퍼의 반이 빈 상태가 될 때까지 통보하지 않는 것이다. 송신자 측도 윈도우 사이즈가 커질 때까지 기다리는 것이다



end