Transport Layer Basic

Process-to-Process

4계층에서 IP Address로 컴퓨터는 찾았으나 안에 어느 프로세스에게 데이터를 전달할 지 찾는 작업이다. 일반적으로 하나의 컴퓨터 안에서는 여러 가지 프로그램이 동작한다. 지금 이 순간만 하더라도 인터넷 브라우저를 켜고 카카오톡 등이 켜져있다. 이때 전달되는 데이터가 본인의 컴퓨터까지 전달된 이후 어떤 프로그램에게 전달될 지를 결정한다는 뜻이다.

image

일반적인 형태는 서버/클라이언트 아키텍쳐이며, 4가지의 정보(Local Host, Remote Host, Locl process, Remote process) 가 필수적이다.

실제 줄에서 컴퓨터를 찾는 것이 MAC Address, 네트워크에서 호스트를 찾는 것 IP Address, 프로그램을 찾는 것 Port 라고 정의할 수 있다.

image

프로그램을 작성하는 경우 IP와 포트를 묶어 Socket Address라 부른다.

image

Port

포트 번호의 0~1023은 대부분 미리 약속되어있다. 만약 임의의 포트를 사용한다면 1024번부터 사용하는 것이 좋다.

image

Multiplexing/Demultiplexing

어플리케이션들이 Transport Layer의 프로토콜을 이용하기 위해서는 프로세스마다 Socket을 이용해야 한다고 했다.하지만, 컴퓨터에는 여러개의 어플리케이션들이 돌아가고, 각각의 어플리케이션들은 하나 이상의 Socket을 생성할 수 있다. 따라서 Transport layer 입장에서는 여러개의 Socket에서 데이터들이 쏟아지는 형태가 된다.이렇게 여러 어플리케이션의 Socket들이 데이터를 송/수신하므로 필요한 개념이 바로 Multiplexing과 Demultiplexing이다.

  • Multiplexing : 여러 어플리케이션의 Socket들로부터 들어오는 데이터를 수집하여, 패킷으로 만들어 하위 레이어로 전송하는 것

  • Demultiplexing : 하위 레이어로부터 수신된 패킷을 올바른 Socket으로 전송하여 올바른 어플리케이션에게 전송하는 것. 이때 정확한 어플리케이션의 Socket으로 전달해주기 위해 포트넘버를 활용한다.

image

Connectionless vs Connection-Oriented

UDP 와 TCP 의 차이점을 꼽으라면 가장 먼저 등장하는 것이다. 이후에 더 자세히 설명하도록 하겠다.

  • Connectionless : UDP - 에러 검출이나 흐름제어를 안한다 Unreliable. 대신 빠름
  • Connection-Oriented : TCP - 에러 검출 흐름 제어 다 하니 Reliable 대신 느림

image

User Datagram Protocol, UDP

Datagram

앞에 있는 패킷과 뒤에 있는 패킷의 상관관계가 없다. 가장 중요한건 프로세스 to 프로세스이며 즉 포트번호가 필요하다. 가장 중요한 기능은 포트를 집어넣을 수 있게 된 것이다. 최소한의 오버헤드를 가지면서 식별 정보를 포함한다. 신뢰성을 보장하지 않아도 되는 작은 메세지를 주고받을 때 사용하며 예로 Ping이 있다. 이는 유실될 수 있다는 가정하에 보내는 것이다.

Frame format

  • UDP Header

Checksum 으로 에러 검출, 또 Port Address가 있는 것을 볼 수 있다. 다시 한번 말하지만 프로세스 식별이 가장 중요한 기능이다!

image

Operation

이제 UDP 에서 서버와 클라이언트의 데이터 전송이 어떻게 이루어지는 지 살펴보자.

먼저 서버는 클라이언트가 언제 데이터를 보낼 지 모르니 항상 클라이언트보다 먼저 살아있어야한다. 연결 설정 과정이 없기에 클라이언트는 데이터를 그냥 보내버려서 유실될 가능성도 있다. 클라이언트는 서버로 데이터를 보내기 전 랜덤 포트 번호를 OS에서 받는다. 서버는 예약된 포트 번호가 있지만 클라이언트의 포트 번호는 랜덤이다. 이런 요청을 UDP 프로토콜에 전달하면 포트 번호를 기반으로 헤더를 만들고 5계층 이상의 메세지에 헤더를 붙여 보낸다.

레이어에는 위아래 송수신 역할을 하는 버퍼가 있다. 만약 이 버퍼가 오버플로우가 나면 5계층에 데이터가 꽉찼다고 말할 수 있다. 데이터를 받을 때, 3계층에서 IP가 메세지를 받아 UDP에 주면 시간 여유가 있을 때 확인해서 포트번호에 따라 어플리케이션에 데이터를 전달한다.

image

Transmission Control Protocol, TCP

Stream-Oriented Protocol

TCP는 Byte 단위로 흘러가는 것이 매우 중요한 특징이다. 패킷이 아니라 Byte이다!

image

유한한 버퍼를 가지고 있다. Sender 버퍼의 회색은 보냈지만 ACK가 안오고 분홍은 아직 안보냈다는 뜻이다. 하얀색은 비어있다는 뜻이다. 버퍼의 단위는 Byte. Reveive 버퍼의 분홍은 받았지만 아직 읽지않았다는 뜻이다.

image

실제 TCP에서 주고 받는 단위를 Segment라 부른다. 당연히 헤더도 붙는다. Segment들이 Byte를 실어나른다고 볼 수 있다.

image

Segment format

CheckSum으로 헤더 에러 체크, Sequence num / Ack num 으로 바이트 번호를 체크한다. 수신 버퍼의 사이즈를 알려주는 Window size, UDP와 동일하게 Address들이 존재한다. Conntection-oriented를 위한 빨간색 Control field 가 존재한다!

image

Control field

1이면 Enable, 0이면 Disable.

  • Syn(연결 설정 요청)
  • Fin(연결 해제 요청)
  • RST(현재 TCP 통신을 초기화)
  • ACK(주고받은 메세지를 잘받고 못받음, 1이면 ACK 필드가 유의미)

image

TCP Operation

Connection Establishment

TCP의 연결 설정 과정이다. 클라이언트가 서버에 8000번과 SYN 을 보내며 연결을 요청한다. 이를 받은 서버는 잘 받았다는 ack에 8001번을 보내고, 15000번과 함께 SYN + ACK 을 보낸다. 이를 다시 클라이언트가 받아서 자신도 잘 받았다는 ack를 15001번과 함께 보내면 connection이 완성된다.

만약 SYN이 너무 많이 들어오면 Flooding Attack으로, 버퍼가 다 차버리는 경우가 존재한다.

image

Data transfer

이제 TCP 연결을 했으니 실제 데이터를 주고받아야한다. 서로 8000번과 15000번은 ack 로 채웠으니 8001번과 15001번부터 데이터를 담아 보낼 수 있다.

먼저 클라이언트가 서버에게 1000바이트를 보낸다. 이는 8001번부터 9000번까지 담아 보낼 수 있다. 다시 한번 1000바이트를 보내면 똑같이 9001번부터 100000번까지 담아 보낸다. 이때 서버가 클라이언트에게 2000바이트를 보내는 동시에 ack 에 10000번까지 잘 받았으니 다음에는 10001번부터 줘! 하며 10001을 보낸다. 클라이언트는 잘 받았으면 ack에 17001을 담아 보낸다.

데이터를 주고받는 과정에서 두 가지 세밀한 방식이 더 존재한다.

  • Pushing Data : 어플리케이션이 보내는 입장에서 바로 보내라! 윈도우가 채워질때가지 기다리지 않는다. 보통 보낼 데이터를 버퍼에 담아두고 한 번에 넘겨주지만 버퍼에 담아두지 않고 바로 내보내는 것이다.
  • Urgent Data : 수신하는 입장에서 Urgent한 걸 꺼내서 바로 올려준다. Urgent 메세지의 위치를 저장하는게 헤더에 있다. 동일하게 수신한 것도 버퍼에 담아 한 번에 올라오지만 급한 데이터는 바로바로 올리라는 뜻이다.

위의 두 가지 방법을 실제 사용하는 사례는 그렇게 많지 않다고 한다.

image

Connection termination

데이터 전송이 모두 끝났으면 연결 해제 과정이 필요하다. 보통은 클라이언트가 먼저 연결을 해제한다. 연결 설정과 비슷하게 FIN 을 보내면 서버가 FIN + ACK 를 보내고 클라이언트가 마지막으로 ACK 를 보내면서 연결이 해제된다. 이때 지금까지 데이터를 주고받으며 사용한 번호 x, y에서 각자 잘 받았다는 의미로 x+1, y+1 이 이루어진다.

image

이때 클라이언트가 연결 해제 요청을 했지만 서버가 아직 보낼 데이터가 남아있는 경우 FIN 에 대해 ACK 로만 응답한다. 그리고 자신이 보낼 데이터를 모두 보낸 이후 FIN 을 다시 보내고 이에대해 클라이언트가 ACK 를 응답하면 연결이 해제된다.

image

Flow Control

window size를 정해서 알려준다. 처음 서버가 클라이언트에게 800바이트를 받을 수 있다고 알려준다. 연결 설정 과정이 끝난 이후 클라이언트가 200 바이트를 보내면 이제 남은 윈도우는 600이라고 ACK에 담아 알려준다. 이후 서버에서 200을 처리하면 윈도우 크기를 다시 늘리고 윈도우를 슬라이딩 시킨다.

이때 서버가 200의 데이터를 받은 이후 이 데이터가 곧장 처리되어 윈도우가 다시 800이 되지 않는다! 데이터가 서버에 온다고 바로 올라가지 않기 때문이다. 윈도우를 어느정도 채워야 데이터를 위로 올려줄 수 있다.

image

Timer

데이터를 받자마자 ACK를 보내면 연속해서 들어오는 데이터에 대해서 계속해서 ACK를 보내줘야한다. 이러지 않고 연속된 데이터에 대해서는 모든 데이터를 잘 받았다는 ACK 하나로만 처리하고자 한 것이다. 따라서 ACK를 바로 보내지 않고 타이머를 설정 후 한번에 보낸다. 이를 통해 느리고 효율이 떨어지는 데이터링크를 더 효율적으로 사용할 수 있다.

  • 장점 : 통신 링크의 효율
  • 단점 : 대량의 데이터를 보내는 경우 효율이 떨어짐, 긴급한 메세지

그림과 같이 서버에서 데이터를 두 번 보냄에 있어서 Ack:7001 을 보내 7000번까지 모두 잘 받았으니 7001번을 보내달라한다. 따라서 서버는 Ack:6001이 오지 않았지만 그 전에 보낸 데이터도 모두 잘 도착했음을 알 수 있다.

image

Lost segment

모든 데이터에 대해서 Ack 를 보내지 않으니 데이터가 유실되었을 때 문제가 발생할 수도 있다. 만약 중간에 701-800 이 Lost 되었지만 서버는 801-900 을 받았다. 따라서 801-900 을 받아 저장해놓고 클라이언트에게 Ack:701 을 보냄으로써 701번을 보내달라고 요청한다. 따라서 에러검출을 위해 타이머를 추가했다고 할 수 있다.

image

오지 않은 데이터의 자리를 Receiver 버퍼에 비워놓은 상태에서, 클라이언트 쪽에 ACK가 세번 이상 오면 타이머를 리셋하고 바로 재전송해준다. 빠르게 에러를 검출하고 복구 가능해졌다.(Fast retransmission)

image

Lost ACK

이번에는 클라이언트가 서버에게 데이터를 잘 전송했지만 서버의 Ack 가 유실된 경우이다. 서버의 Ack:701 은 클라이언트에게 도착하지 않았지만 Ack:901 이 클라이언트의 타이머가 끝나기 전에 도착했기에 클라이언트는 서버가 모든 데이터를 잘 받았음을 알 수 있다.

image

클라이언트는 타이머를 통해 Ack 가 도착하지 않자 처음부터 데이터를 다시 보내지만 서버는 700번까지 이미 받은 데이터이기에 곧장 Ack:701 을 보낸다. 그러면 클라이언트는 601-700 을 다시 보내지 않아도 된다.

image

Slow start

처음 TCP 를 연결하고 클라이언트와 서버가 통신할 때 통신 속도의 한계를 모른다. 따라서 처음에는 부하를 크게 주지 않으면서 속도의 한계를 찾아가며 동작하는 방법이다. 연결설정하고 첫번째 데이터가 나갈때부터 적용된다. 윈도우 사이즈에 상관없이 보내는 양을 조절한다. 언제 부하가 걸릴지 모르니 두배씩 늘려가며 확인하며 부하가 걸리는 양을 찾는다.

image

Congestion avoidance

양을 두 배씩 늘리면 너무 급수적으로 늘어나기에 적당한 값에서는 데이터의 양을 +1 씩 늘려가는 경우이다.

image

Taho TCP

두 동작을 합친 방법이다. 여기서 TIme out 이란 지연이 발생하거나 오버플로우가 일어났다는 뜻으로 통신이 제대로 안된다는 것이다. 처음 slow start 하다가 congest advanced를 적용시킨다.

Time-out 발생 기준 가장 마지막으로 성공한 송신을 ssthresh로 잡는다. 아래 그림에서는 8에서 Time-out 이 발생했기 때문에 4부터 Congest advanced로 바꾼다. 에러가 나면 다시 Congest 를 줄인다. 6까지 slow start하고 다시 6부터 Congest를 적용한다.

하지만 네트워크에서 에러가 꾸준하게 발생하면 애초에 네트워크 구성의 잘못이 크다. 따라서 Time-out 이 발생한다고 그때마다 속도를 팍팍 떨어트리는 것은 잘못된 방법이다.

image

Reno TCP

어느 시점에 우연히 한순간에 트래픽이 몰려서 Time-out 이 발생할 수 있다. 에러가 나면 조금만 낮췄다가 다시 올리자는 방법이다.

image

업데이트:

댓글남기기