시퀀스 번호와 재전송 — TCP 는 도착했음을 어떻게 확인하는가
바이트 하나하나에 번호를 매기고, ack 번호 = 다음에 원하는 바이트로 답을 맞춘다. 도착하지 않았을 때의 2 가지 알아채는 방법 — 재전송 타이머와 중복 ACK — 를 구별한다.
「도착했을 것」을 어떻게 확인하는가
제 1 장에서 본 대로, IP 는 잃어버린 것을 알려 주지 않습니다. 그런데도 TCP 는 「반드시 도착한다, 도착하지 않으면 알아챈다」를 약속합니다. 장치는 매우 소박해서, 택배의 송장 번호와 수령 사인과 닮았습니다.
중요한 것은, 번호가 패킷마다가 아니라 바이트마다 매겨져 있다는 점입니다. TCP 에게 데이터는 「바이트의 흐름」이며, 세그먼트(패킷에 실리는 단위)는 그 흐름을 편의상 자른 조각에 지나지 않습니다. 세기 시작하는 번호를 앞 장의 핸드셰이크에서 합의했으므로, 양쪽은 처음부터 같은 잣대로 바이트를 셀 수 있습니다. 이후의 예에서는 읽기 쉽도록 세기 시작을 1000 으로 하고, 최초의 데이터 바이트를 1001 로 합니다.
seq = 1001 로 500 바이트의 세그먼트는 바이트 1001〜1500 을 운반하고, ACK 는 「다음에 원하는」 1501 을 가리킵니다. 번호의 주역은 세그먼트가 아니라 바이트입니다.
ack 번호 = 다음에 원하는 바이트의 번호
캡처를 읽는 데 있어 가장 큰 급소가 ack 번호의 해석입니다. 「어디까지 받았는가」가 아니라 「다음에 어디부터 원하는가」를 가리킵니다. seq = 1001 부터 500 바이트를 받았다면, 도착한 마지막 바이트는 1001 + 500 − 1 = 1500 번. 그래서 돌려주는 ack 는 1501 입니다.
또 하나의 급소가 누적 확인 응답이라는 성질입니다. ACK 는 「여기까지는 빠짐없이 연속으로 받았다」는 것밖에 표현할 수 없습니다. 중간의 3001〜4000 이 빠진 채 4001〜5000 이 도착해도, 돌려줄 수 있는 ack 는 3001 그대로. 도착한 분량은 수신 버퍼에 보관해 두고, 구멍이 메워진 순간 ack 는 단숨에 5001 까지 뜁니다. 이 「보관해서 다시 정렬하는」 움직임이야말로 약속 그 2, 「순서대로」의 실체입니다.
소문제 3-1 — seq 와 ack 를 손으로 계산한다
캡처를 읽는 힘은 이 계산이 모든 것의 토대입니다. 바이트의 범위를 종이에 써서 확인해 주세요.
Q1. 송신 측이 seq = 1001 의 세그먼트로 500 바이트의 데이터를 보냈습니다. 수신 측이 이것을 받고 돌려주는 ack 번호는 얼마입니까.
이 세그먼트가 운반하는 것은 바이트 1001〜1500 의 500 바이트입니다(1001 + 500 − 1 = 1500). ack 번호는 「다음에 원하는 바이트의 번호」이므로, 1500 의 다음인 1501 을 돌려줍니다. 「받은 마지막 번호」가 아니라 「다음에 원하는 번호」 — 이 1 의 어긋남을 몸에 익히는 것이 캡처를 읽는 첫걸음입니다.
Q2. 수신 측은 바이트 3000 까지 연속으로 수신 완료했습니다. 거기에 중간의 3001〜4000 을 건너뛰고 4001〜5000 의 세그먼트가 도착했습니다. 수신 측이 돌려주는 ack 번호는 얼마입니까.
TCP 의 ACK 는 누적 확인 응답입니다. 「여기까지는 빠짐없이 연속으로 받았다」는 것밖에 말할 수 없으므로, 4001〜5000 이 수중에 있어도, 빠져 있는 3001 보다 앞으로는 나아갈 수 없습니다. 도착한 4001〜5000 은 수신 버퍼에 보관되고, ack = 3001 을 돌려줍니다. 이 「같은 ack 를 반복한다」는 움직임이 후반의 중복 ACK 의 복선입니다.
Q3. TCP 의 시퀀스 번호가 「세그먼트(패킷)마다」가 아니라 「바이트마다」 매겨져 있는 것의 이점은 어느 것입니까.
TCP 가 운반하는 것은 바이트의 흐름이지, 패킷의 나열이 아닙니다. 재전송 시에 여러 세그먼트를 다시 묶거나, 경로의 사정으로 분할되거나 하여 세그먼트의 경계는 바뀔 수 있지만, 바이트 단위의 번호라면 어떻게 다시 잘라도 「어디까지 도착했는가」가 하나로 정해집니다. 이 「세그먼트가 아니라 바이트가 주역」이라는 관점은 제 6 장의 프레이밍 문제로도 직결됩니다.
알아채는 방법 1 — 침묵(재전송 타이머)
ACK 가 돌아오지 않을 때, 얼마나 기다리면 「잃어버렸다」고 판단해도 될까요. 너무 짧으면 낭비되는 재전송으로 네트워크를 압박하고, 너무 길면 사용자를 기다리게 합니다. TCP 는 보낼 때마다 왕복 시간(RTT: 보내고 나서 ACK 가 돌아올 때까지의 시간)을 계속 측정하고, 그 평균과 편차로부터 재전송 타임아웃(RTO)을 동적으로 계산합니다. 같은 건물 안이라면 몇 밀리초, 대륙 간이라면 수백 밀리초 — 회선에 맞춰 잣대가 바뀌는 것입니다.
RTO 가 만료되면 빠진 세그먼트를 재전송하고, RTO 를 배로 늘려서 다음을 기다립니다(지수 백오프). ACK 가 돌아오지 않는 가장 유력한 원인은 혼잡이므로, 다시 보낼수록 간격을 벌려서, 혼잡에 몰아치기를 피하는 설계입니다.
알아채는 방법 2 — 비명(중복 ACK)과 빠른 재전송
침묵을 기다리는 것보다 빠른 방법이 있습니다. 바이트 8000 까지 도착한 후에 8001〜9000 이 손실되고, 그 후속만 계속 도착하면, 수신 측은 도착할 때마다 ack = 8001 을 돌려줄 수밖에 없습니다. 송신 측에서 보면 같은 번호의 ACK 가 반복해서 도착한다 — 이것이 중복 ACK 입니다.
중복 ACK 는 1 통마다 「후속은 도착했는데, 8001 부터의 구멍이 메워지지 않는다」고 말하고 있습니다. 같은 것이 3 회 도착하면, 송신 측은 더 이상 기다리지 않습니다. 후속이 도착하고 있다 = 경로는 살아 있다 = 빠진 것은 아마 1 개라고 추리하고, RTO 를 기다리지 않고 seq = 8001 의 세그먼트만을 재전송합니다. 이것이 빠른 재전송입니다.
캡처에서 재전송을 발견하면, 어느 쪽의 재전송인지를 봐 주세요. 중복 ACK 유래라면 가벼운 단발 로스, 타임아웃 유래라면 응답이 전혀 돌아오지 않는 심각한 상태 — 같은 「재전송」이라도 해석은 정반대입니다.
소문제 3-2 — 도착하지 않았음을 어떻게 알아채는가
TCP 에는 「도착하지 않았다」를 알리는 통지가 없습니다. 침묵과 중복이라는 2 가지 간접 증거로 추리합니다.
Q4. 재전송 타이머(RTO)의 설명으로 올바른 것은 어느 것입니까.
RTO 는 「이만큼 기다려서 ACK 가 오지 않으면 잃어버렸다고 간주한다」는 임계값으로, RTT 의 측정값과 흔들림으로부터 동적으로 정해집니다. 근거리라면 짧게, 원거리라면 길게. 재전송해도 여전히 ACK 가 오지 않으면 대기 시간을 배로 계속 늘려(지수 백오프), 혼잡한 네트워크에 몰아치기를 하지 않도록 합니다. 수신 측은 「도착하지 않았다」를 통지할 수 없습니다 — 도착하지 않은 것은, 도착하지 않았다고 알아챌 수 없기 때문입니다.
Q5. 송신 측에 같은 ack 번호의 ACK(중복 ACK)가 몇 번이나 도착하는 일이 있습니다. 수신 측에서 무엇이 일어나고 있습니까.
누적 확인 응답의 귀결입니다. 바이트 8000 까지 수신 완료로 8001〜9000 이 빠진 채 후속(9001〜, 10001〜…)이 도착하면, 수신 측은 그때마다 ack = 8001 을 돌려줄 수밖에 없습니다. 즉 중복 ACK 는 「그 뒤는 도착하고 있는데, 여기만 빠져 있다」는 수신 측의 비명입니다. 버퍼 가득참은 윈도우 0 의 광고(제 4 장)로 전해지며, 이것과는 별개입니다.
Q6. 같은 중복 ACK 가 3 회 도착한 시점에서, 송신 측은 타임아웃을 기다리지 않고 빠진 세그먼트를 재전송합니다(빠른 재전송). 타임아웃을 기다리지 않고 보내도 좋다고 판단할 수 있는 근거는 어느 것입니까.
중복 ACK 는 후속 세그먼트가 도착할 때마다 생겨납니다. 즉 3 회 도착했다면, 적어도 3 개의 후속이 무사히 도착하고 있다 — 경로는 살아 있고, 빠진 것은 아마 1 개뿐. 그렇다면 RTO 의 만료(수백 밀리초〜초 단위의 침묵)를 기다리는 것은 낭비입니다. 타임아웃 재전송은 침묵으로부터의 추리, 빠른 재전송은 도착하고 있다는 증거로부터의 추리. 장애 로그에서 어느 쪽의 재전송이 일어나고 있는가에 따라, 네트워크 상태의 해석이 달라집니다(제 5 장·제 7 장).
이 장에서 가져갈 것
- 번호는 바이트마다. seq = 1001 의 500 바이트는 바이트 1001〜1500 을 운반한다
- ack 번호 = 다음에 원하는 바이트의 번호. 게다가 누적 확인 응답 — 구멍보다 앞으로는 나아갈 수 없다
- 로스를 알아채는 방법은 2 가지. 침묵(RTO 만료, 지수 백오프)과 비명(중복 ACK 3 회 → 빠른 재전송)
- 중복 ACK 유래의 재전송은 경증, 타임아웃 유래의 재전송은 중증의 신호
여기까지로 「반드시 도착한다·순서대로」의 구조가 갖춰졌습니다. 다음 장은 약속 그 3 의 전반 — 상대의 사정에 맞추는 슬라이딩 윈도우입니다. ACK 에 합승해 오는 「앞으로 몇 바이트 받을 수 있는가」라는 숫자가 주역이 됩니다.