본문 바로가기
학교공부/[컴퓨터 네트워크]

[컴퓨터 네트워크] - Transport layer_TCP

by 윈디개 2025. 5. 26.

 이전 글까지는 TCP를 배우기 위해 사전지식인 rdt(stop and wait 프로토콜)과 Go-Back-N, Selective repeat에 대해서 정리해 보았다. 이번 글에서부터는 본격적으로 Transport layer 계층 프로토콜인 TCP에 대해서 정리해보려고 한다.


1. TCP 프롤로그

 본격적으로 TCP에 대해서 알아보기 전에, TCP의 전반적인 특징을 정리해보려고 한다.

  • point-to-point : 1 대 1 통신으로 이루어진다.
  • reliable, in-order byte steam : byte의 순서 유지를 보장한다.
  • full duplex data : 양쪽 방향 데이터 흐름이 가능하다.
  • cumulative ACKs : ACK를 받은 그 시점에 다음에 받을 packet 번호에 대한 ACK를 보낸다.
  • pipelining : TCP congestion and flow control을 가능하게 하고, window size를 설정
  • connection-oriented : 연결을 위한 handshaking 작업 필요
  • flow controlled :  sender는 receiver의 상태를 절대 압도하지 않는다.

2. TCP segment structure

이제 TCP의 구조에 대해서 알아보자. 먼저 다음 그림을 살펴보자.

 

위 그림은 TCP segment의 구조를 나타낸 것이다. 먼저, 기본적으로 TCP의 header는 20 bytes + options의 크기를 가진다.(참고로 UDP는 8 byte였다.)

 

이제 차례대로 설명해보면,

  • source port # : 패킷을 보내는 측 port 번호
  • dest port # : 목적지 port 번호
  • sequence number : data 부분의 시작 byte에 해당하는 수가 들어감(전체 중에 어디에 위치하는 지)
  • acknowledgement number : 다음으로 받길 기다리는 seq # 
  • head len : TCP 헤더 길이
  • C, E : congestion control 관련
  • A : 지금 보내는 응답이 ACK이다.
  • R(Reset) : 이 플래그가 활성화 되어 있으면 비정상적 종료
  • S : 이 플래그 활성화 되어 있으면 싱크 맞추기(TCP 연결을 요청)
  • F(Finish) : 연결 끊기
  • receive window : 흐름 제어를 위한 field(receiver 측에서 여유 공간의 크기를 보낼 때 사용)
  • checksum : checksum field
  • Urg data pointer : 긴급 데이터 필요시 field 활성화(데이터 영억의 특정 부분을 가리킴)
  • options : 웬만하면 쓰지 않는 필드(얘 때문에 헤더 길이가 가변길이가 됨)

3. TCP Sequence Number & ACKs

 이제 TCP의 sequence #와 ACK에 대해서 알아보려고 한다.

  • Sequence # : 데이터가 실려서 전송되는 부분에 첫 번째 데이터의 바이
  • Acknowledgements : 다음으로 받을 sequence #를 ACK #로 보낸다(+cumulative ACK)

TCP는 Go-Back-N 방법과 Selective repeat 방법과 다르게 byte마다 sequence number를 붙여서 byte stream을 보내게 된다. Tcp segment structure와 동시에 비교해보면서 seq #와 ACK #의 흐름을 다음 그림을 통해 확인해보자.

 

 

위 그림을 설명하면,

  1. 파란색 segment의 첫 부분을 400이라고 하고, 노란색 segment 첫 부분을 300이라고 하면,
  2. receiver 입장에서는 현재 노란색 부분에 대해서 도착하고 있는 상태이다.
  3. 이 때, receiver는 399까지 다 받았기 때문에, A flag를 활성화 시키며
  4. 다음으로 도착할 패킷 번호인 400을 acknowledgement number field에 실어 보낸다.
  5. ACK를 받은 sender는 다음 데이터를 보낼 때, sender의 TCP segment structure의 sequence number = 400이 된다.

4. TCP round trip time & Timeout

 TCP를 정리하기 전, TCP를 위한 사전지식을 정리하며, timeout이란 개념이 자주 등장했다. 그럼 이런 timeout은 어떻게 정할까? 

 

 기본적으로는 RTT보다는 당연히 길게 잡아야된다. 그렇지만, 여기서 고려해야 할 점은, 네트워크 상황이 변하기 때문에 RTT의 값도 가변적이라는 것이다. 

  • timeout을 만약 너무 짧게 잡는다면, 불필요한 재전송이 많아질 것이고,
  • timeout을 만약 너무 길게 잡는다면, segment 손실에 대한 재전송이 너무 늦게 일어날 것이다.

 

 위의 상황들을 고려해, 적절한 RTT를 추정한 뒤에 timeout을 설정하는 것이 좋다. 다음과 같은 RTT 측정법을 알아보자.

  • Sample RTT: segment를 전송하고 ACK가 올 때까지 시간을 측정한 시간

 이 Sample RTT로 timeout을 설정하게 되면 다음과 같은 문제가 생길 수 있다.

 

위 그림을 설명하면,

  1. segment를 하나 보냈는데, timeout이 일어나 재전송을 했다.
  2. 재전송을 한 뒤 얼마 지나지 않아 ACK가 도착했다.
  3. 이 때, Sample RTT를 측정해서 timeout을 재설정 해야되는데,
  4. RTT가 재전송에 대한 ACK 기준으로 설정해야 되는지, 처음 시도에 대한 ACK 기준으로 설정해야 되는지 애매해진다.
  5. 가장 최신 재전송에 대한 RTT로 측정하면 너무 짧은 RTT, 그 반대면 너무 긴 RTT가 발생한다.

 

 이런 Sample RTT에 대한 문제를 해결하기 위해서, 과거의 a%를 반영하고, 현재의 (100-a)%를 반영해 RTT를 설정하는 방법인 EstimatedRTT가 등장했다.

 

EstimatedRTT = (1-a)*EstimatedRTT + a*SampleRTT

 

위와 같은 식으로 EstimatedRTT를 표현할 수 있다.

 

 보통 a = 0.125로 설정하는데 이 값이 의미하는 바는 최근 결과 즉, sample RTT를 압도적으로 반영하지 않는다는 것이다. 다음 표를 살펴보면,

파란색 점으로 표현된 부분이 그 시점의 sampleRTT, 분홍색 점이 EstimatedRTT이다. 즉, sampleRTT(최근 값)를 0.125만큼만 반영하게 되면 EstimatedRTT값은 크게 변동하지 않게 된다. 따라서, 그나마 일정한 RTT값으로 timeout을 설정할 수 있게된다.

 

그렇지만, 위 그래프를 보면 특정 시점에 SampleRTT의 변동 폭이 큰 것을 알 수 있다. 네트워크 상황에 따라 RTT의 값이 크게 바뀌게 되는데, 이러한 이유로 EstimatedRTT로만으로는 timeout 값을 설정하지 않는다. 이러한 방법을 EWMA(Exponential Weighted Moving Average)라고 한다.

 

 Timeout을 더 세밀하게 설정하기 위해서, 위와 같은 그래프에서의 큰 차이를 고려하기 위해서, EstimatedRTT에 safety margin을 더하게 되는데, 이때

safety margin = 4*DevRTT

이다. 

 

즉, TimeoutInterval은 다음과 같은 식으로 나타낼 수 있다.

TimeoutInterval = EstimatedRTT + 4*DevRTT

 

DevRTT는, deviation, 즉, RTT의 분산을 뜻하는데, 다음과 같은 식으로 나타낸다.

DevRTT = (1-b) * DevRTT + b * |SampleRTT - EstimatedRTT|

일반적으로, b=0.25로 설정한다. 우항의 b에 곱해진 식은 최신결과를 반영하는 것이고, (1-b)에 곱해진 식은 과거의 값을 반영하는 것인데, 이를 통해 EWMA 방식과 유사하게 최신결과를 조금만 반영한다는 것을 알 수 있다.


5. TCP Sender & Receiver

 이제 본격적으로, TCP Sender와 Receiver가 각각 무슨 역할을 하는지 알아보려고 한다.

 

-TCP Sender

 TCP Sender가 하는 일을 간단하게 나열하면 다음과 같다.

  • seq #와 함께 segment를 만든다. (이때, seq #는 segment의 첫 데이터 바이트 숫자이다.)
  • timer를 시작한다.
    • 가장 먼저 보낸 segment기준으로 시작.
    • timeout = TimeOutInterval(앞서 정리한 EstimatedRTT + 4*DevRTT)
  • timout이 일어나면 segment를 재전송하고, timer를 재시작한다.
  • ACK를 받으면, 해당 ACK에 대해서 ACKed상태로 업데이트 하고, unACKed segment가 있으면 timer 재시작한다.

-TCP Receiver

 TCP Receiver가 하는 일을 간단하게 나열하면 다음과 같다. 

Event at receiver TCP receiver action
받을 것으로 기대되는 segment가 순서대로 도착했고, 그 전까지의 segment들은 이미 ACKed된 상태 ACK을 delay시킨다. 다음 segment를 500ms까지 기다렸다가, 다음 segment가 도착하지 않으면 ACK를 보낸다.
받을 것으로 기대되는 segment가 순서대로 도착했지만, 이전의 다른 segmanet의 ACK가 pending인 상태 해당 ACK에 대한 single cumulative ACK를 즉시 보내고, 다시 순서대로 ACKing한다.
받을 것으로 기대되는 segment가 순서가 뒤바뀌어 도착했고, 기대되는 seq #보다 큰 상태이다. 즉, seq # 사이의 Gap이 탐지 됐다. 즉시 그전의 duplicate ACK를 보내서 패킷 loss가 발생했다고, 재전송이 필요함을 알린다. 
받을 것으로 기대되는 segment가 전체적으로 도착하지 않는다. 즉시 그 전 ACK를 보내 비상임을 알려 재전송이 필요함을 알린다.

 


6. TCP Retransmission

 

먼저 왼쪽 그림에 대해서 설명하면,

  1. 92번 부터 8개의 segment를 보냈다.
  2. Host B는 ACK = 100(다음 번으로 받을 segment  #)을 보냈지만 중간에 손실됐다.
  3. Host A에서 ACK = 92에 대한 timeout이 발생해 retransmission이 발생한다.
  4. Host B는 중복된 segment를 받았지만 다시 ACK = 100을 보내고 Host A도 ACK을 받는다.

왼쪽 그림을 통해 ACK 손실 시 재전송을 하고, Receiver는 중복 데이터라도 ACK만 보내면 된다는 것을 이해할 수 있다.

 

오른쪽 그림을 설명하면,

  1. 92번 부터 8개의 segment를 보낸다.
  2. 연속적으로 100번 부터 20개의 segment를 보낸다.
  3. Host B가 ACK = 100을 보내고, ACK 120을 순서대로 보낸다.
  4. 위 ACK들이 도착하기 전에 92에 대한 timeout이 발생
  5. 92부터 8개의 segment 재전송
  6. 그 뒤에 ACK 100, 120이 차례대로 Host A로 도착한다.
  7. Host A의 window에서는 send base가 차례대로 100, 120으로 이동한다.
  8. B는 100을 보낼 필요 없이 cumulative ACK = 120을 보낸다.
  9. Host A는 ACK = 120을 이미 받아 send base가 120인 상태지만, 재전송한 segment가 이미 ACK 되었음을 확인한다.

오른쪽 그림을 통해 cumulative ACK을 활용하는 TCP의 방식을 알 수 있다.

 

다음 그림을 살펴보자.

위 그림에 대해서 설명하면,

  1. 92부터 8개의 segment를 보낸다.
  2. 그 후 연속으로 100부터 20개의 segment를 보낸다.
  3. 중간에 ACK 100을 전송했지만 손실됐고,
  4. ACK 120은 전송해서 Host A에 잘 도착했다.
  5. 그 후, Host A는 ACK 100을 받지 못했지만 cumulative ACK를 통해 ACK 120을 받아 100도 잘 도착했다고 판단하고,
  6. 그 다음 segment를 보낸다.

 

이제, TCP의 fast retransmit를 알아보자.

 

다음 그림을 먼저 살펴보자.

 

위 그림 상황을 설명하면,

  1. 92번 부터 8개의 segment를 보내고
  2. 그 뒤 연속으로 100~ 20개의 segment, ... 계속해서 보낸다.
  3. Host B는 100번 부터 20개의 segment만 받지 못했고, 나머지 segment들은 잘 받았다.
  4. 그렇지만, 중간에 못 받은 100번에 대한 ACK를 계속해서 보내는 상태이다.

이때, sender가 3개의 중복된 ACK를 받는다면, timeout이 되지 않았더라도 빠르고 해당 segment를 재전송하는 fast retransmission이 TCP에 구현되어 있다. 


7. 정리

이번 글에서는 TCP의 기본 개념, segment 구조, 그리고 sender와 receiver의 동작 과정을 정리하였다.
이 글에서 기억해야 될 것은 다음과 같다.

  • TCP의 header 구조(20 byte + optional)와 각 field가 하는 역할,
  • TimeoutInterval : EstimatedRTT + 4 * DevRTT
  • TCP의 retransmission

등이 있다.

 

 다음 글에서는 TCP에서 중요한 기능들인 TCP flow control, congestion control에 대해서 정리해 볼 예정이다.