요약

  • 수신 윈도우가 0이라는 것은 수신자가 현재 새 바이트를 받아들일 여유가 없다는 유효한 지시이며, 상대 시스템·경로·애플리케이션이 실패했다는 증거가 아니다.
  • 윈도우를 다시 연 ACK는 순수 ACK라서 신뢰성 있게 재전송되지 않으므로, 송신자는 광고된 윈도우가 0인 동안에도 주기적으로 프로브를 보내야 한다. 그 응답은 일반 데이터 전송의 허가를 주지 않으면서 현재 관측 가능한 윈도우를 복원한다.
  • 프로브가 확인 응답되는 한 TCP는 연결을 계속 열어 두어야 하며, 그럼에도 RFC 6429는 애플리케이션과 운영체제가 로컬 자원을 회수하고 명시적으로 중단할 권한을 유지한다.

교착은 올바른 두 개의 침묵에서 시작되었다

전송 대기 중인 바이트가 더 있는 송신자와, 읽기를 멈춘 애플리케이션을 둔 수신자를 상상해 보자. 수신 버퍼가 차고, 수신자는 윈도우 0을 광고하고, 송신자는 이를 따라 새 데이터 전송을 멈춘다.

이후 애플리케이션이 버퍼링된 바이트를 일부 소비한다. 수신자는 0이 아닌 윈도우를 담은 ACK를 보낸다. 그 패킷이 도착하면 작업이 재개된다. 유실되면 어느 쪽도 TCP를 위반하지 않았다. 송신자는 여전히 유효한 영(0) 윈도우 보고를 들고 있고 일반 데이터 허가도 없다. 수신자는 이미 새로운 여유를 알렸고, 확인해 줄 새 데이터가 없을 수도 있다. 따라서 두 개의 올바른 침묵이 잘못된 공유 사실을 영원히 유지할 수 있다.

RFC 1122는 이 위험을 직접적으로 기술한다. ACK만 있는 세그먼트는 신뢰성 있게 전송되지 않는다. 영(0) 윈도우 프로빙이 없으면, 윈도우를 여는 ACK의 유실로 연결이 무기한 멈출 수 있다. 따라서 신뢰성에는 미확인 페이로드의 재전송만으로는 부족했고, 허가 자체를 회복하는 방법이 필요했다.

윈도우는 진단이 아니라 허가였다

RFC 813은 수신 윈도우를 흐름 제어 도구로 기술했다. 수신자는 자신이 받아들일 준비가 된 버퍼 여유를 대략적으로 보고하고, 송신자는 이미 전송 중인 데이터를 제외한 사용 가능한 윈도우를 계산한다.

그 숫자의 권한은 좁다. 0은 일반적인 윈도우 아래에서 새 바이트를 보낼 수 없다는 뜻일 뿐, 여유가 왜 사라졌는지는 말하지 않는다. 프로세스가 느리거나, 일시 정지되었거나, 백프레셔를 받거나, 사람을 기다릴 수 있다. 호스트와 네트워크는 완벽하게 동작 중일 수 있다.

표준이 남긴 오래된 예는 소박하다. 프린터의 용지가 떨어져 프린터 애플리케이션이 데이터를 받기를 멈춘다는 것이다. 이 정지는 몇 분, 몇 시간, 몇 날까지 이어질 수 있다. 0을 전송 계층 실패로 다루면 증거 없이 애플리케이션 상태를 연결 판정으로 바꿔 버린다.

또한 수신 윈도우는 혼잡 윈도우가 아니다. 하나는 엔드포인트가 얼마나 받아들일 수 있는지를 표현하고, 다른 하나는 경로에 얼마나 나르도록 요청해야 하는지를 제한한다. 수신자는 혼잡하지 않은 경로에서 여유가 없을 수도 있고, 네트워크가 혼잡한 상태에서 여유가 넉넉할 수도 있다. 이 신호들을 결합하면 잘못된 계층에 잘못된 상태에 대한 권한을 주게 된다.

단 한 옥텟의 예외가 현재의 진실을 물었다

RFC 793이 원래의 장치를 제공했고, 통합된RFC 9293이 이를 유지한다. 윈도우가 0인 송신자는 가용한 새 데이터가 있으면 적어도 한 옥텟을, 없으면 재전송을 통해 주기적으로 수신자를 프로브한다. 수신자는 다음 기대 시퀀스 번호와 현재 윈도우를 보여주는 ACK로 응답한다.

이 예외는 쉽게 오해된다. 프로브는 수신자의 통제권을 빼앗거나 윈도우 크기만큼의 트래픽을 허가하지 않는다. 윈도우가 0인 수신자가 반드시 답해야 하는 유한한 질문을 보낼 뿐이다. 여유가 여전히 0이면 ACK는 0을 확인한다. 여유가 다시 열렸다면, 앞서 유실된 업데이트가 전달하지 못한 새 허가가 ACK에 담겨 온다.

첫 프로브는 윈도우가 한 번의 재전송 타임아웃 기간 동안 0으로 유지된 뒤 이루어져야 한다. 이후 프로브는 지수 백오프를 사용해야 한다. 이 타이밍은 단 한 번의 유실된 업데이트에는 빠르게 대응하면서, 합법적인 긴 정지를 상시 폴링으로 만들지 않는다. 표준은 의도적으로 하나의 보편적인 최대 간격을 두지 않았다.

답변된 0은 존재의 증거였다

RFC 1122는 TCP가 제공되는 수신 윈도우를 무기한 닫아 둘 수 있도록 허용한다. 수신자가 프로브를 계속 확인 응답하는 한, 송신자의 TCP는 연결을 계속 열어 두어야 한다.

이 규칙은 진전을 보장하지 않는다. 증거의 의미를 보존한다. 확인 응답된 프로브는 상대 TCP와 되돌아오는 경로가 현재 보고로 응답했음을 보여준다. 애플리케이션이 건강한지, 사람이 용지를 보충할 것인지, 송신자가 자신의 큐를 영원히 유지할 여력이 있는지는 보여주지 않는다.

이 구분은 운영적으로 중요하다. 응답이 없으면 상대나 경로에 대한 불확실성이 커진다. 0을 보고하는 ACK는 상대가 존재하면서 여유를 유보하고 있다는 긍정적 증거다. 둘에 같은 타임아웃 판정을 적용하면, 프로토콜이 애써 회복한 정보를 버리게 된다.

영속성이 메모리에 대한 권리를 만들지는 않았다

무기한이라는 표현의 규칙은 나중에 로컬 자원 회수에 대한 금지로 잘못 읽혔다.RFC 6429는 전송 계층 계약을 바꾸지 않으면서 그 해석을 바로잡았다. 애플리케이션이나 운영체제는 persist 상태에 있는 연결을 포함해 연결의 중단을 요청할 수 있고, TCP는 이를 따라야 한다.

그 문서는 이 구분이 왜 필요한지 보여주었다. 많은 클라이언트가 큰 응답을 요청하고, 읽기를 멈추고, 윈도우 0을 광고하고, 프로브를 계속 확인 응답할 수 있다. 서버는 원격으로는 유지 비용이 싸지만 로컬로는 비싼 상대들을 위해 큐에 담긴 응답 데이터와 연결 상태를 계속 보유한다. 이런 연결이 충분히 쌓이면 TCP 버퍼와 제어 블록이 고갈될 수 있다.

보편적인 숨겨진 전송 계층 타임아웃은 해답이 아니다. 그 연결이 합법적인 인쇄 작업인지, 계약상 장기 전송인지, 적대적인 자원 점유인지 알 방법이 없다. 서비스 약속, 테넌트, 큐 비용, 마감을 아는 계층이 중단 결정을 소유해야 한다. TCP는 공유 대화의 일관성을 유지하고, 로컬 정책이 계속하는 것이 가치 있는지 판단한다.

너무 조금씩 다시 여는 것도 또 다른 함정을 만들었다

수신자가 여유를 쓸 수 없을 만큼 조그마한 조각으로 반환하면, 신뢰성 있는 재개만으로는 부족하다. RFC 813은 Silly Window Syndrome을 문서화했다. 작은 윈도우 증가가 작은 세그먼트, 더 많은 확인 응답, 높은 CPU 비용, 유실과 재전송으로 이어지는 안정된 패턴이다. 그 메모는 현장의 심각한 사례를 보고했지만, 그 측정치는 보편적인 성능 상수가 아니라 예시다.

수신자 측 회피는 유용한 양을 알릴 수 있을 때까지 작은 증가를 의도적으로 유보한다. 송신자 측 회피는 권한의 오른쪽 경계가 조금 움직였다는 이유만으로 조그마한 조각을 보내지 않으려 한다. RFC 9293은 두 형태를 모두 요구하며, Nagle 알고리즘을 보완물로 다룬다. Nagle은 작은 애플리케이션 쓰기를, SWS 회피는 작은 허가의 이동을 다룬다.

따라서 persist와 SWS 회피는 정반대의 경계를 보호한다. 수신자는 몇 바이트의 여유가 생길 때마다 촐랑거려서는 안 된다. 그러나 일단 의미 있는 재개를 알렸다면, 그 알림이 사라졌을 때 송신자가 그 사실을 다시 발견할 수 있어야 한다.

가장 작은 공유 메커니즘이 로컬의 선택을 보존했다

이 역사는 RFC 793의 메커니즘에서 출발해, RFC 813의 성능 분석, RFC 1122의 호스트 요구 사항, RFC 6429의 자원 권한 명확화, 그리고 RFC 9293의 통합 규칙으로 이어진다. 오래 지속된 설계는 타이머 값이 아니라 책임의 분배였다.

수신자가 현재 여유를 통제한다. 송신자의 TCP는 그 여유가 변할 때 알아내기 위한 드문드문한 방법을 유지한다. 전송 애플리케이션과 운영체제는 기다리면서 얼마나 많은 상태, 시간, 비용을 투자할지 결정한다.

그래서 TCP는 어떤 비용을 치르더라도 기다리겠다고 약속하지 않으면서 영(0)에서 persist하는 법을 배웠다. 프로토콜은 허가를 회복 가능하게 만들면서도, 권한을 주는 쪽이 다른 기계의 자원을 소유하게 만들지 않을 수 있다.

출처와 한계

근거 자료는RFC 793,RFC 813,RFC 1122,RFC 6429,RFC 9293이다. 이 문서들은 의미와 명시된 위험을 확립하며, 모든 운영체제의 현재 기본값, 현재 공격 빈도, 특정 애플리케이션의 건강 상태를 확립하지 않는다.