본문 바로가기
네트워크

[네트워크] Chap 3.5 - TCP reliable data transfer

by 개발 고양이 2024. 11. 23.

TCP reliable data transfer

TCP는 unreliable한 IP의 위에서, rdt를 해준다.

- pipelining을 통해, out-of-order를 탐지 가능 → in-order-delivery가 가능

- cumulative acks

- single retransmission timer per connection

 

Retransmission

TCP는 loss 등 뭔가 문제가 발생했을 경우 재전송을 한다.

재전송은 크게

① timeout이 발생한 경우

② 3 duplicate ACK을 받은 경우 (timeout 이전에 빨리 재전송하는 방법이다)

2가지 상황일때 시작된다.


TCP sender events:

1. data received from app

  • (NextSeqNumber - SendBase) = number of unacked bytes
    즉 아직 잘 도착했다고 확신할 수 없는 inflight bytes 개수임.
  • Window size, W 가 (NextSeqNumber - SendBase) 와 같다면?
    => 이미 보낼만큼 다 보냈으므로 application msg를 소켓으로 보내도 sending TCP는 더 이상 전송X
  • 만일 (W - (NextSeqNumber - SendBase))= N이라 하면, N bytes 만큼 전송 가능하다는 뜻
    만일 응용이 보낸 메시지 크기가 M  bytes 이고 M이 N 보다 큰 경우 (MㅡN) bytes는 sending buffer에서 대기

 

2. timeout

  • timeout이 발생하면, timeout이 발생한 해당 segment를 재전송 후 timer restart
  • ack이 안된것 중에 가장 옛날에 보낸 segment를 다시 보낸다! (즉 not ack 중 가장 작은 seq #를 가진 segment를 재전송)
  • socket당 한개의 timer를 관리
    TCP의 timer는 항상 oldest unacked segment를 pointing 
    timeout 시 timer가 가리키고 있는 byte # (= Sendbase) "부터" 재전송 시작

 

3. ACK received

ACK = y 를 수신한 경우

  • y <= send base
    예를 들어 y = 180, send base가 201이라고 하자.
    201을 받았다는건 receiver쪽에서 up to 201까지 싹 다 받았다는 의미이므로, 180은 이미 필요없는 정보이다.
    따라서 아무것도 하지 않는다.

  • y == send base
    → duplicated ACK!

TCP Receiver: ACK generation

 

in-order한 segment를 수신한 경우 (모든 segment들은 이미 ACK을 받음)

=> 다음 segment를 잠시 기다리며 delay를 시켰다가 segment가 안오면 한꺼번에 ACK을 보낸다.

 

in-order한 segment를 수신한 경우 (ACK이 아직 오지 않은 segment가 있음)

=> 즉시 하나의 cumulative ACK을 보낸다.

 

out-of-order segment를 수신한 경우

=> 순서를 벗어난 segment가 왔다는건 현재 기대하고 있는 sequence number보다 큰 번호의 segment가 왔다는 뜻이다. (즉 일정구간을 건너뛰고 왔다는 것) 따라서 그 즉시 duplicate ACK을 보낸다. (받기를 원하는 sequence number를 담아서)

 

gap을 부분적으로 or 완전히 채우는 segment가 도착한 경우

=> 즉시 ACK을 보낸다. (추가적인 윈도우 공간이 생기기 때문에 그걸 sender에게 알려주고 window를 슬라이딩)


TCP: retransmission scenarios

 

lost ACK scenario (ACK이 loss된 경우)

A가 SequenceNumber 92로 8byte의 데이터를 보내면

B는 ACK에 100을 넣어서 보낸다. (92~99까지 데이터가 잘 왔으므로 100번째 byte를 보내라는 의미)

하지만 이 ACK이 Host A에게 가다가 loss되었다면?

timeout이 발생하여 A는 다시 동일한 segment를 전송한다.

 

premature timeout (ACK이 느리게 도착한 경우)

2개의 segment가 연속해서 전송된다고 가정한다.

B는 각각의 segment를 잘 받아서 각각에 대한 ACK을 보냈다.

ACK은 A에 잘 도착하였지만, 첫번째 ACK을 받기도 전에 timeout이 발생하는 바람에 A는 첫번째 segment를 재전송하다.

B는 재전송한 segment를 받는다. 근데 이때 이미 (timeout 이전에) Seq=100, 20byte 데이터를 받았던 상태이므로 ACK=120을 전송한다!

ACK for 120 => 두번째 받은 segment, 즉 20 byte를 keep하고 있다는 뜻!

(Host A가 다시 보낸 segment가 도착했을 때, B는 이미 seq 119까지 받은 상태

=> 120번째 데이터를 받을 차례임. 따라서 ACK = 100이 아닌, ACK = 120을 전송)

 

 

 

cumulative ACK

똑같이 여러개의 segment를 보냈다고 가정하자. 근데 이번에는 첫번째 segment에 대한 ACK이 loss되고, 두번째 segment에 대한 ACK은 잘 전송되었다. 

A는 두번째 segment에 대한 ACK 120만 받은 상황이다. 

하지만, 못받은 첫번째 ACK은 신경쓰지 않는다. 왜냐하면 ACK = 120을 받았다는건, 119번째 byte까지는 B에게 잘 전송되었다는 의미이기 때문이다. 

즉 앞에서 못받은 ACK은 무시해도 괜찮으며, 이와 같은 cumulative ACK은 unnecessary retransmission을 방지한다.

ACK=100은 loss되었으나, ACK=120을 받았음 → 119까지 잘 도착했다는 뜻! => SendBase는 120이 된다.

 


TCP fast retransmit

TCP sender sets up long timeout and uses fast retx for rdt.
1. timeout value 값을 RTT 보다 크게 여유있게 잡아놓는다.
2. pipelining으로 보낸 것에 대한 receiver의 cumulative ACK으로 중간에 loss된 segment가 있다는 것을 유추
3. timeout 전에 retransmission을 시작

TCP fast retransmit

pipelining하게 여러개의 segment들을 전송하고 있다.

이때 Seq=100인 segment가 B에게 전송 중 유실되었다.

Seq=100이 B에 도착하지 않았으므로, B는 그 이후로 Segment들을 받을 때마다 ACK=100을 계속해서 A에게 전송한다.

=> 이 말은, 동일한 ACK이 여러번 전송되는 경우 어떠한 segment가 loss되었다고 판단할 수 있다는 뜻이다.

 

따라서 TCP 표준에서는, 3개의 중복된 ACK을 받으면 loss로 판단한다.

이를 3 duplicate ACK이라고 부른다.

=> 3 duplicate ACK을 받으면, unacked segment 중 smallest Sequence number를 가진 segment, 즉 가장 오래된 segment를 재전송한다.