TCP: 두 판 사이의 차이

youngwiki
52번째 줄: 52번째 줄:
RTT의 평균값뿐만 아니라, 그 변동성을 측정하는 것도 중요한데, RTT의 변동성은 '''DevRTT'''라고 한다. DevRTT는 SampleRTT가 EstimatedRTT로부터 평균적으로 얼마나 벗어나는지를 추정한 값이며, 아래 공식을 통해서 나타낸다.  
RTT의 평균값뿐만 아니라, 그 변동성을 측정하는 것도 중요한데, RTT의 변동성은 '''DevRTT'''라고 한다. DevRTT는 SampleRTT가 EstimatedRTT로부터 평균적으로 얼마나 벗어나는지를 추정한 값이며, 아래 공식을 통해서 나타낸다.  
  <math>DevRTT = (1-\beta)\times DevRTT+\beta \times |SampleRTT-EstimatedRTT|</math>
  <math>DevRTT = (1-\beta)\times DevRTT+\beta \times |SampleRTT-EstimatedRTT|</math>
  <math>typically,\, \beta = 0.25</math>
  typically, <math>\beta = 0.25</math>


==각주==
==각주==

2025년 4월 5일 (토) 06:50 판

상위 문서: Transport Layer

개요

TCP(Transmission Control Protocol)는 연결 지향형(connection-oriented)이라고 불린다. 왜냐하면, 한 프로세스가 다른 프로세스에게 데이터를 보내기 시작하기 전에, 양쪽 프로세스는 먼저 서로 handshake를 수행해야 하기 때문이다. 즉, 데이터 전송에 앞서 몇 개의 초기 segment를 주고받아, 앞으로의 데이터 전송을 위한 매개변수를 설정해야 한다. 이러한 handshaking은 TCP가 riliable하고, in-order한 byte stream을 제공하도록 한다. 이때, TCP 연결은 항상 point-to-point이며, 이는 단 하나의 송신자와 단 하나의 수신자 사이에 연결이 형성된다는 것을 의미한다.
또한, TCP 연결은 양방향(full-duplex) 서비스를 제공한다. 즉, 한 호스트의 프로세스 A와 다른 호스트의 프로세스 B 사이에 TCP 연결이 있으면, application layer의 데이터는 A → B로 흐름과 동시에 B → A로도 흐를 수 있다. TCP는 그 외에도 flow control, congestion control과 같은 여러 서비스도 부가적으로 제공한다.

TCP segment Structure

Figure 1. TCP segment structure
Figure 1. TCP segment structure

TCP가 다루는 데이터의 단위는 세그먼트(segment)이며, 세그먼트는 헤더 필드들과 데이터 필드(payload)로 구성된다. 데이터 필드는 application layer의 데이터의 일부(청크)를 담는다. 세그먼트의 데이터 필드 최대 크기는 MSS(Maximum Segment Size)에 라고 불린다. TCP가 웹페이지의 이미지처럼 큰 파일을 전송할 때, 보통 해당 파일을 MSS 크기의 청크로 나눈다.[1]

Figure1은 TCP 세그먼트의 구조를 보여준다. UDP와 마찬가지로 TCP 헤더에는 송신자/수신자의 port 번호가 포함되어 있으며, 이는 multiplexing/demultiplexing에 사용된다. 또한 UDP와 마찬가지로 checksum field도 있다. 그리고 sequence number 필드와 ACK 필드는 TCP가 rdt 서비스를 구현하는데 사용된다.

Sequence Numbers and Acknowledgment Numbers

TCP 세그먼트 헤더에서 가장 중요한 필드 중 두 가지는 시퀀스 번호(sequence number) 필드와 ACK(acknowledgment number) 필드이다. 이 필드들은 TCP의 신뢰성 있는 데이터 전송 서비스를 구성하는 데 있어 핵심적인 부분이다.

Sequence Number

Figure 1. Dividing file data into TCP segments
Figure 1. Dividing file data into TCP segments

TCP는 데이터를 구조화되지 않았지만, 순서가 있는 바이트의 스트림(stream of bytes)으로 본다. 즉 어떤 "메시지의 단위"와 같은 개념이 아니라 데이터를 단순히 바이트가 나열된 stream으로 본다. 이때, 바이트 스트림은 세그먼트의 헤더 필드를 제외한 payload로만 구성되어 있다. 예를 들어, 500,000바이트짜리 파일을 보내면 TCP는 이를 연속된 바이트들로 보고, 각 바이트에 0, 1, 2, ..., 499999와 같이 순서 번호(시퀀스 번호) 를 매긴다. 이때, 시퀸스 번호는 세그먼트 안의 데이터가 바이트 스트림에서 어디서 시작하는지를 나타내는 번호이다.

예를 들어, MSS가 1000바이트이고, 파일의 크기가 500,000바이트라면 500개의 세그먼트가 생긴다. 이때 각각의 세그먼트에는 바이트 스트림 내의 시작 바이트가 시퀸스 번호로 들어간다. 첫 번째 세그먼트는 바이트 0~999에 해당하며, 시퀸스 번호가 0이다. 두 번째 세그먼트는 바이트 1000~1999에 해당하며, 시퀸스 번호가 1000이다. 세 번째 세그먼트는 바이트 2000~2999에 해당하며, 시퀸스 번호가 2000이다. 이와 같은 방식으로 각 세그먼트는 자신이 바이트 스트림 내에서 어디서 부터 시작하는 데이터인지를 시퀀스 번호로 알려준다.

이때, 예시에서는 시퀀스 번호를 0부터 시작한다고 했지만, 실제 TCP는 각 연결마다 무작위 시퀀스 번호(ISN)를 선택한다.

Acknowledgment Number

ACK은 반대측에서 받을 것으로 기대하는 바이트의 시퀸스 번호를 말해주는 값이다. 예를 들어, A가 B에게 데이터를 받고 있고, A가 B로부터 0~535번 바이트를 받았다면, A는 B에게 보낼 TCP 세그먼트의 ACK 필드에 536을 넣는다. 즉, ACK는 ‘수신측이 현재까지 이 바이트까지 받았고, 그 다음 바이트부터 달라’는 의미를 갖는 번호이다.
이번에는 호스트 A가 호스트 B로부터 시퀀스 번호 0번부터 535번까지의 바이트를 포함한 세그먼트 하나와, 시퀀스 번호 900번부터 1,000번까지의 바이트를 포함한 또 다른 세그먼트를 받았다고 하자. 이때 어떠한 이유로 A가 536번부터 899번까지의 바이트를 받지 못했다면, 이 경우 A는 누락된 바이트 스트림을 복원하기 위해서 시퀸스 번호 536을 가지는 새그먼트를 받고자 한다. 따라서 A가 B로 보내는 다음 세그먼트의 ACK 필드에는 536이 들어간다. 즉, TCP는 바이트 스트림 내에서 처음으로 누락된 바이트에 대한 ACK을 전송하기 때문에 TCP는 cumulative acknowledgment을 사용한다고 볼 수 있다.

Handing out of order

TCP는 세그먼트가 순서대로 도착하지 않는 상황(out-of-order)을 어떻게 처리할지에 대해서 RFC에서 강제하지 않으므로, 구현자에게 어떻게 처리할지를 맡긴다. 이 경우 선택지는 두개이다. 하나는 순서대로 도착하지 않은 세그먼트는 그냥 폐기하는 방식이다.[2] 다른 하나는 순서대로 도착하지 않은 세그먼트를 버퍼에 저장하고, 누락된 세그먼트를 수신하면 이어붙이는 방식이다.[3]
예를 들어, 두 번째 세그먼트가 도착하기 전에 세 번째 세그먼트가 도착했다면, 첫 번째 방식은 세번째 세그먼트를 그냥 폐기하는 것이고, 두번째 방식은 세번째 세그먼트를 버퍼에 보관한 이후, 두 번째 세그먼트가 도착하면 바이트 스트림을 복원한다. 이때 두 번째 방식이 네트워크 효율성이 더 높으므로, 대부분의 TCP 구현은 두 번째 방식을 택한다.

즉, TCP 구현은 cumulative ACK을 사용한다는 점에서는 Go-Back-N 방식과 유사하지만, 순서에 어긋난 세그먼트를 버퍼에 보관하고 이를 활용한다는 점에서는 Selective Repeat 방식과 유사하다. 따라서 TCP는 Go-Back-N 방식보다는 Selective Repeat에 더 가까운 하이브리드 방식으로 구현된다고 볼 수 있다.

Telent: Example for Sequence and Acknowledgment Numbers

Figure 2. Simple telent application over TCP
Figure 2. Simple telent application over TCP

이 문단에서는 RFC 854에서 정의된 Telnet 프로토콜을 이용해 간단한 상황에서 시퀸스 번호와 ACK이 어떻게 사용되는지에 대해 다룬다. 호스트 A와 호스트 B가 Telent 프로토콜 세션을 이용해 통신을 하고, 호스트 A가 세션을 시작하므로 클라이언트이고, 호스트 B는 서버에 해당한다. 이 상황에서는 A가 문자 c를 입력하면, c가 서버로 전송되어 c의 복사본을 클라이언트의 화면에 띄운다.
오른쪽의 그림처럼, 클라이언트와 서버의 초기 시퀸스 번호(ISN)가 42와 79이라면 아래와 같이 세개의 세그먼트가 서로간에 전송된다.

  • 첫 번째 세그먼트는 클라이언트에서 서버로 전송된다. 데이터 필드에는 문자 'c'의 1바이트 ASCII 코드 값이 들어있으며, 시퀸스 번호는 42이다. 클라이언트는 서버로 부터 아무 데이터를 받지 않았으므로, ACK는 79이다.(서버가 보낼 다음 바이트)
  • 두 번째 세그먼트는 서버에서 클라이언트로 전송된다. 이 세그먼트는 클라이언트로부터 받은 데이터에 대한 ACK을 답신하며[4], 그와 동시에 문자 'c'를 다시 클라이언트로 에코하기 위해 데이터 필드에 'c'의 ASCII 코드 값을 포함한다. 이렇게 세그먼트에 ACK를 데이터 세그먼트에 함께 실어서 보내는 방식은 piggybanking이라고 부른다.
  • 세 번째 세그먼트는 클라이언트에서 서버로 전송된다. 해당 세그먼트의 목적은 서버로부터 받은 데이터에 대한 ACK을 답신하는 것이다. 해당 세그먼트는 데이터 필드가 비어있으므로, piggybank 방식이 아니다. 해당 ACK의 값은 80이고, 시퀸스 번호는 43이다.

Round-Trip Time Estimation and Timeout

TCP는 rdt3.0 프로토콜과 마찬가지로 손실된 세그먼트를 복구하기 위해 타임아웃/재전송(timeout/retransmit) 메커니즘을 사용한다. 이때 timeout interval을 설정하는 것은 까다로운 문제이다. 이때, timeout interval은 RTT보다는 길어야 한다.

EstimatedRTT

RTT를 추정히기 위해서는 SampleRTT를 활용한다. SampleRTT는, 세그먼트를 전송한 시점(즉, IP로 전달한 순간)과 그 세그먼트에 대한 ACK을 받은 시점 사이의 시간이다. 이때 재전송된 세그먼트에 대해서는 SampleRTT를 계산하지 않으며, 한번만 전송된 세그먼트에 대해서만 측정된다. 이때 SampleRTT 값은 라우터 내의 혼잡이다 end system의 부하에 따라, 각각의 세그먼트에 따라 달라지며, SampleRTT는 매우 다양하게 나타난다. 따라서 EstimatedRTT라는 개념을 활용하여 SampleRTT 값들의 어떠한 평균을 계산한다. 이때 EstimatedRTT는 새로운 SampleRTT 값을 얻을 때마다 TCP는 EstimatedRTT를 다음 공식으로 업데이트된다:

EstimatedRTT=(1α)×EstimatedRTT+α×SampleRTT
typically, α=0.125

EstimatedRTT는 SampleRTT 값들의 EWMA(Exponential Weighted Moving Average)이다. 해당 가중 평균은 최근의 측정값이 더욱 비중있게 반영되며, EstimatedRTT의 업데이트가 반복됨에 따라 과거의 SampleRTT의 가중치는 지수적으로 감소한다. 이를 통해서 현재의 네트워크 혼잡 상태를 더욱 잘 반영할 수 있다.

DevRTT

RTT의 평균값뿐만 아니라, 그 변동성을 측정하는 것도 중요한데, RTT의 변동성은 DevRTT라고 한다. DevRTT는 SampleRTT가 EstimatedRTT로부터 평균적으로 얼마나 벗어나는지를 추정한 값이며, 아래 공식을 통해서 나타낸다.

DevRTT=(1β)×DevRTT+β×|SampleRTTEstimatedRTT|
typically, β=0.25

각주

  1. 단, 마지막 청크는 MSS보다 작을 수 있다
  2. Go-Back-N 방식에 해당한다.
  3. Selective Repeat 방식과 유사하다.
  4. ACK 번호를 43으로 설정하여, 서버는 바이트 42까지 성공적으로 받았고 43번 이후를 기다리고 있다고 알린다.