송신 측과 수신 측의 데이터 처리 속도 차이를 제어하기 위한 기법이다.
흐름제어와 혼잡제어가 살짝 헷갈리기도 하는데, 이렇게 이해하면 편하다.
혼잡의 정의는 “여럿이 한데 뒤섞이어 어수선함”이라는 뜻을 가진다. 네트워크에서 수신 측과 송신 측에도 여러 패킷이 모이기는 하지만 네트워크 중간에서 패킷을 중계하는 라우터에 더 많은 패킷이 뒤섞일 것이고 이를 제어하는 것이 혼잡 제어이다. 우리가 명절에 차가 막힐 때 고속도로에서 차가 막히는 경우를 생각하면 된다.
흐름제어는 “A지점에서 B지점으로 진행됨”이라는 의미를 가진다. 즉, 흐름은 중간 과정보다 시작지점과 종료지점을 조금 더 강조하는 단어이다. 따라서 흐름 제어는 송신지와 수신지를 관리하는 제어 방법이라 할 수 있다. 명절에 출발 톨게이트, 혹인 도착지 톨게이트 쪽에 차가 막히는 상황이라고 생각하면 된다.
정리하자면 흐름제어는 통신을 수행하는 두 지점인 “점”을 제어하겠다는 것이고 혼잡제어는 통신을 하는 과정인 “선”을 제어하겠다는 것이다.
흐름제어에 대한 설명으로 돌아가자면 흐름 제어는 송신 측과 수신 측 사이의 데이터 처리 속도를 제어하여 수신자의 버퍼 오버플로우를 방지한다.
TCP 통신에서 패킷을 송/수신할 때 송신 측에선 송신할 패킷을 TCP 버퍼에 잠시 저장했다 보내고 수신 측에선 수신할 패킷을 바로바로 처리할 수 없으므로 일단 TCP 버퍼에 수신한 패킷들을 저장해 놓는다.
그런데 만약 수신 측의 처리 속도(수신 측 TCP 버퍼가 비는 속도) 보다 송신 측의 패킷 전송량이 많을 경우 전송된 패킷의 일부가 수신 측 TCP 버퍼에 저장되지 못하는 상황이 발생한다. 이 경우 전송된 패킷의 일부가 소실될 수 있다.
이런 문제를 막기 위해 흐름제어를 통해 수신 측에서 감당하지 못할 정도의 많은 데이터를 송신 측에서 보내지 않도록 제어하는 것이다.
출처 : https://afteracademy.com/blog/what-is-stop-and-wait-protocol/
송신 측에서 전송한 패킷에 대한 ACK를 받아야지만 다음 패킷을 전송할 수 있는 흐름 제어 방식이다.
이 구조를 사용한다면 패킷을 확실하고 안정적이게 보낼 수는 있을 것이다. 패킷을 보낸다는 것은 이전 패킷이 정상적으로 처리되었다는 것과 동일한 의미이기 때문이다.
하지만 이 방법은 패킷을 하나씩만 보내야 하므로 대기 시간(Waiting Time)이 매우 길어지는 매우 비효율적인 방법이다.
슬라이딩 윈도우를 알기 위해선 “윈도우”라는 개념부터 알아야 한다.
윈도우는 송신, 수신 스테이션 양쪽에서 만들어지는 TCP 버퍼의 크기를 말한다.
위에서도 잠시 설명했지만, 네트워크 통신을 수행할 때 송신 측은 버퍼에 TCP 세그먼트를 보관한 후 순차적으로 전송하며 수신 측은 도착한 TCP 세그먼트를 애플리케이션이 읽을 때까지 TCP 버퍼에 저장하게 된다.
즉, 송/수신 과정에서 일시적으로 TCP 세그먼트를 보관하는 공간이 TCP 버퍼이자 “윈도우”인 것이다.
모든 컴퓨터가 동일한 윈도우 크기를 가지고 있지 않다. 따라서 서버와 클라이언트가 통신을 수행하기 전 상대방의 윈도우 크기를 파악하는 과정이 선행되어야 한다.
즉, TCP 연결 과정인 3-way Handshake 과정에서 통신 상대의 윈도우 크기를 파악하는 것이다.
윈도우 크기는 ACK 신호를 보낼 떄 TCP 헤더에 같이 담아 보냄으로써 계속해서 윈도우 크기를 조절하게 된다.
이전에 배웠듯 TCP 헤더에는 Window Size를 저장하는 공간이 존재한다. 따라서 ACK 신호를 받았다면 Window Size에 저장된 값을 파악하여 상대방이 어느 정도의 패킷을 수신할 수 있는지 파악하고 그에 따라 송신할 패킷 양을 조절할 수 있는 것이다. 연결 과정인 3-way Handshake에서는 ACK 신호를 보낼 때 TCP 버퍼가 모두 비어있는 상태일 것이므로 기기의 TCP 버퍼 크기가 곧 윈도우 사이즈가 될 것이다.
슬라이딩 윈도우란 송신 측에서 ACK 신호를 받지 않아도 설정된 윈도우 크기만큼의 패킷을 한번에 전송할 수 있게 하는 방법이다.
이 동작 방식을 이해하기 위해선 2가지 그림을 동시에 보는 게 좋을 것 같다.
먼저 TCP 연결 과정(3-way Handshake) 과정을 통해 윈도우 사이즈를 정했을 것이다. 그림 1에선 7, 그림 2에선 2로 정해졌다.
송신지는 수신지에서 ACK 신호가 오기 전까지 윈도우 사이즈만큼의 패킷을 보낼 수 있다.
이는 그림 2를 보면 이해가 쉬운데 ACK 2가 오기 전 윈도우 사이즈에 저장되어 있는 패킷 0,1이 모두 전송되었음을 볼 수 있다. 또한 패킷 2는 윈도우 사이즈에 속해있지 않았으므로 보내지 않았음을 확인할 수 있다.
수신자는 데이터를 받고 처리한 뒤 ACK 신호를 송신자에게 보낼 것이다.
ACK 신호를 받은 송신 측에서는 수신 측에 보낸 패킷이 모두 정상적으로 도착하여 처리되었음을 확인하였으므로 윈도우 사이즈를 맞춰주기 위해 슬라이딩 윈도우의 경계를 오른쪽으로 확장한다.
이는 그림 1을 보면 이해가 쉽다. 0, 1 패킷을 보낸 뒤 ACK 2가 왔다. 즉 송신지에선 패킷 0, 1이 정상적으로 도착했음을 알 수 있다. 이후 송신지의 윈도우 사이즈는 7이기 때문에 현재 슬라이딩 윈도우(5)의 크기를 맞춰주기 위해 경계를 오른쪽으로 2개 옮기는 것이다. 결국 7과 2번째 0이 슬라이딩 윈도우 범위 내에 들어갔음을 확인할 수 있다.
이런 과정을 데이터가 모두 송신될 때까지 반복함으로써 슬라이딩 윈도우 기법을 통해 데이터를 보낼 수 있는 것이다.
문제는 슬라이딩 윈도우 기법을 사용할 경우 그림 2처럼 중간에 소실되는 패킷이 존재할 수 있다.
이러한 소실 패킷을 처리하는 방법이 고안돼야 했으며 이 때문에 "오류 제어"라는 2번째 TCP 제어 기법이 등장하게 된다.
오류 제어는 TCP 통신 중 데이터가 유실되거나 잘못된 데이터가 수신되었을 경우 대처하는 제어 방식을 의미한다.
흐름 제어와 혼잡 제어는 송신하는 패킷의 양을 조절하는 제어 기능이었다면 오류 제어는 패킷이 중간에 소실되었을 경우 소실된 패킷이 무엇인지를 파악한 뒤 해당 패킷을 재전송하는 다른 성격을 가진 제어 방식이다.
오류 제어의 핵심 로직은 "오류 검출"과 "재전송"이다. 매우 간단한 개념인데, 오류 제어는 "어떤 패킷이 잘못 송신되었는지 검출"하고 해당 패킷을 "재전송"하는 제어 방식인 것이다. 이를 위해 오류 제어에서는 ARQ(Automatic Repeqt Request) 기법을 사용해 잘못 송신된 패킷을 재전송함으로써 오류를 복구한다.
단지 재전송은 네트워크에 흐르는 패킷의 양을 많게 하며 동일한 패킷을 2번 보내는 비효율적인 과정으로 적을수록 좋으며 이 때문에 흐름제어와 혼잡 제어가 병행되어야 하는 것이다.
데이터를 송신한 측이 ACK 신호를 받지 못했다는 것은 두 상황 중 하나이다.
송신한 패킷이 통신 중 소실되었거나, 패킷이 정상적으로 처리되어 수신 측이 ACK 신호를 보냈지만 ACK 신호가 중간에 소실된 경우이다.
후자의 경우 사실 수신 측에선 패킷을 받은 상태이므로 다시 보내지 않아도 된다.
하지만 TCP 통신 과정에서 전자의 이유로 ACK 신호가 안온 것인지 후자의 이유로 안 온 것인지 파악할 수 없으므로 오류라고 간주하는 것이다.
(항상 최악의 상황을 가정하는 것이 네트워크 이론엔 많이 존재한다.)
중복된 ACK를 받음(3 ACK Duplicated)
이는 아래 혼잡 제어를 설명할 때 자세히 설명할 것이다.
지금 간단히 말하자면 동일한 ACK 번호를 가진 패킷을 3번 이상 받으면 패킷이 정상적으로 송신되지 않았다고 판단하는 것이다.
ACK의 반대되는 신호로 NAK라는 신호가 존재한다.
이 신호 또한 TCP 헤더에 저장된 값으로 수신 측에서 특정 패킷이 도착하지 않았으므로 해당 패킷을 다시 보내달라고 NAK를 통해 요청하는 것이다.
하지만 ACK 만으로도 오류 검출이 충분히 가능하기 때문에 사용하지 않는 경우도 있다.
출처 : https://www.isi.edu/nsnam/DIRECTED_RESEARCH/DR_HYUNAH/D-Research/stop-n-wait.html
흐름 제어에서 설명했던 대로 ACK를 받고 나서 다음 데이터를 보내는 방식이다.
이를 오류 검출에 조금 더 맞게 알아보자.
만약 송신지에서 ACK 신호를 받지 못했다고 가정하자. 그럼 ACK 신호가 소실되었든 송신 패킷이 소실되었든 TCP 통신상 문제가 발생한 것이다.
이 경우 ACK 신호를 일정 시간이 지나도 받지 못하면 Timeout이 발생했다고 판단하여 오류가 발생했다고 인지한다.
그럼 송신지에서는 이전에 보낸 패킷을 다시 보냄으로써 오류 검출 및 재전송을 수행하는 것이다.
Timeout(타임아웃)에 대하여 조금 더 자세히 알아보자.
TCP 통신에서는 패킷을 송신한 뒤 ACK 번호가 돌아오는 것을 기다리는 시간을 타임 아웃이라고 말한다.
이 대기 시간은 너무 길어도 좋지 않고 너무 짧아도 좋지 않으므로 적절한 시간을 찾는 것이 중요하다.
이를 위해 타임아웃 대기 시간을 특정 값으로 고정하지 않고 네트워크 상황에 따라 동적으로 변경하는 방법을 취하고 있는데 ACK 번호가 돌아오는 시간을 기준으로 이를 판단하게 된다
데이터를 송신할 때 ACK 번호가 돌아오는 시간을 계측하고 만약 ACK 번호가 돌아오는 시간이 지연되면 이에 따라 대기 시간을 늘리며 지정된 시간보다 빠르게 도착하면 다시 대기 시간을 짧게 만드는 방식이다.
타임아웃의 최솟값은 0.5~1초로 지정되어 있다.
연속으로 패킷을 보내다 오류가 발생했다고 판단되는 지점 이후의 모든 프레임을 재전송하는 오류 제어 방식이다.
수신 측에서는 정상적으로 받지 못한 패킷이 있을 경우 해당 패킷의 다음 패킷들을 받았다 하더라도 문제가 되는 패킷의 직전 패킷에 대한 ACK를 보낸다.
이러한 성질 때문에 GB을 Cumulative ACK라고도 한다.
말로 하면 좀 어려운데 예시를 들어보자.
송신 측에서 1 ~ 5까지의 패킷을 전송했다고 가정하자. 그런데 수신 측에서는 1, 2, 4, 5 패킷만 받았다.
즉, 수신 측에선 3번째 패킷을 받지 못한 것이다. 이 경우 수신 측에선 4, 5 패킷을 폐기한 뒤 ACK 신호로 2, 3, 3, 3을 보내게 된다. 송신 측에선 ACK 신호를 받은 뒤 3번 패킷부터 소실되었음을 인지하고 3, 4, 5 패킷을 다시 보내게 되는 것이다.
GBN은 송신지에서 전송한 패킷 중 ACK 신호가 돌아오지 않은 가장 최신 패킷에 대해 타이머를 설정한다.
만약 타이머가 만료될 때까지 ACK 신호가 오지 않는다면 해당 패킷부터 전송한 모든 패킷에 대하여 재전송을 시행하는 것이다.
만약 ACK 신호가 정상적으로 도착했다면 다음 전송한 패킷에 대하여 다시 타이머가 설정될 것이다.
GBN의 특성을 가장 잘 나타낼 수 있는 이미지는 위 이미지라고 생각한다.
위 이미지에서 송신지에서 보낸 0, 1, 2 패킷이 수신 측에 정상적으로 도착했다. 하지만 2번 패킷에 대한 ACK 번호가 소실되었다.
이 경우 송신지에선 2번 패킷이 정상적으로 수신지에 도착하지 않았다고 판단한다.
따라서 일정 시간이 지나 2번 패킷에 대하여 Time out이 발생했다면 2번 패킷 이후의 모든 패킷, 즉 2,3,4 패킷을 재전송하게 되는 것이다. 분명 0, 1 패킷이 정상적으로 도착했다는 것을 송신 측에서 인지하였고 이후에 3, 4 패킷을 보낸 것임에도 불구하고 2번 패킷이 정상적으로 도착하지 않았다는 이유만으로 2, 3, 4 패킷이 다시 재전송되는 것이다.
추가로 송신 측에서 재전송을 했는데 수신 측 버퍼에 남아있는 공간이 없는 경우였다면 재전송 패킷 때문에 네트워크가 혼잡해질 수 있다. 송신 측은 계속해서 데이터를 보낼 것이고 수신 측은 버퍼에 공간이 없으니 받은 데이터를 계속 폐기할 것이므로 쓸모없는 패킷의 흐름이 생기는 것이다.
따라서 수신 측에서 ACK를 보내며 남은 TCP 버퍼의 크기(윈도우 크기)를 같이 보내줘 송신 측에 알리게 된다.
GBN ARQ의 가장 큰 단점은 확인된 마지막 프레임 이후의 모든 프레임을 재전송해야 한다는 점이다.
위 이미지에서 볼 수 있듯 3, 4 패킷은 정상적으로 도착했음에도 불구하고 2번 패킷에 대한 ACK 신호가 오지 않았다는 이유로 재전송돼야 하며 이는 네트워크에 흐르는 패킷의 양을 증가시킬 것이다.
이러한 문제점을 해결하기 위해 손상되거나 소실된 패킷만 재전송하는 것이 SR ARQ 방식이다.
소실된 패킷만 재전송하면 되므로 네트워크에 흐르는 패킷을 최소화시킬 수 있기 때문에 장점만 있어 보이지만 SR ARQ에는 큰 약점이 존재한다.
TCP 통신에서는 패킷이 순서대로 도착한다는 것이 보장되지 않는다는 점 때문에 생기는 문제점이다.
SR ARQ는 어떤 패킷이 도착하지 않았는지 알아야 하며 이 때문에 수신 측 버퍼의 데이터가 순차적으로 정렬되어야 할 필요가 있다.
GBN의 경우 1, 2, 5, 4로 도착했다 하더라도 4,5 패킷이 폐기되므로 별 문제가 없지만 SR ARQ에서는 1, 2, 5, 4를 1, 2, 4, 5로 정렬하여 3번 패킷이 오지 않았음을 파악하고 3번 패킷만 재전송을 요청해야 한다.
따라서 정렬의 과정이 추가로 필요하며 이를 위한 별도의 버퍼가 필요하다. 즉, 비용이 증가하는 것이다.
혼잡 제어란 네트워크로 들어가는 패킷의 양을 조절함으로써 네트워크에 너무 많은 패킷이 흐르지 않도록 조절하는 것을 말한다.
만약 한 개의 라우터에 패킷이 몰려 모든 패킷을 처리하지 못할 경우 송신 측에선 라우터가 처리하지 못한 데이터를 손실 데이터로 판단하여 재전송하게 된다. 이전에 말했듯 재전송된 패킷은 네트워크에 흐르는 패킷의 양을 많게 하므로 혼잡을 유발하며 이러한 혼잡은 오버플로우나 데이터 손실을 빈번하게 발생시키는 원인이 된다.
따라서 패킷 재전송에 의한 네트워크 혼잡을 제어하기 위하여 송신 측에서 네트워크로 보내는 패킷의 수를 조절하는데 이를 혼잡 제어라고 한다.
출처 : https://www.learnsteps.com/do-you-know-about-the-aimd-method-in-tcp-congestion-control/
직역하자면 합 증가/곱 감소 알고리즘이다.
처음에는 패킷을 1개만 보내고 문제없이 도착했다면 윈도우 크기를 1씩 증가시키며 전송하는 것이다.
만약 전송에 실패했거나 Timeout이 발생할 경우 윈도우 크기를 반으로 줄인 뒤 패킷을 재전송하게 된다.
위 사진에서 볼 수 있듯 보내는 패킷이 1부터 시작하여 선형으로 증가하다 6개의 패킷을 보낼 때 전송이 실패하였다면 6의 반인 3으로 윈도우 크기를 줄인 뒤 다시 패킷을 전송하는 것이다.
이 방식은 여러 호스트가 1개의 네트워크를 공유하고 있는 경우에도 시간이 지나면 공평하게 패킷을 보낼 수 있다는 장점이 있다.
하지만 윈도우 크기 증가폭이 선형으로 증가하는데 이는 증가폭이 매우 작은 것이다. 따라서 높은 대역폭을 사용하여 효율적인 통신이 진행되기까지 시간이 너무 오래 걸리며 네트워크 혼잡을 미리 감지하는 것이 아닌 혼잡 상황에 닥쳐야지만 대역폭을 줄이는 방식이라는 단점이 존재한다.
출처 : https://www.researchgate.net/figure/TCP-slow-start-and-congestion-avoidance_fig1_262068525
AIMD의 대역폭 증가 폭이 너무 작아 전송 속도 증가 시간이 오래 걸린다는 단점을 보완하기 위해 나온 방식이 Slow Start 방식이다.
Slow Start에선 윈도우 크기를 1, 2, 4, 8... 처럼 2배씩 증가시키며 혼잡이 감지될 경우 윈도우 크기를 1로 줄이는 방식이다.
Slow Start에서 가장 주의 깊게 봐야 하는 것은 "Threshold(ssthresh)"이다. 이 지점은 "임계값"이라고 하는데 윈도우 크기가 임계값 이상이 될 경우 윈도우 크기가 2배씩 증가하는 것이 아닌 AIMD 방식처럼 1씩 증가하게 된다. 혼잡이 감지될 경우 윈도우 크기가 1이 됨과 동시에 Threshold 값 또한 바뀌게 되는데 이 공식은 그렇게 중요하진 않으므로 따로 설명하진 않겠다.
빠른 재전송을 알기 위해선 "3-ACK Duplicated"라는 용어를 알아야 한다. 3-ACK Duplicated란 송신 측이 3번 이상 중복된 ACK 신호를 받은 상황을 의미한다.
네트워크를 잘 공부했다면 알겠지만 수신 측은 송신 측에서 보낸 패킷이 아닌 수신 측에서 처리한 마지막 패킷에 대하여 ACK 번호를 생성하게 된다.
따라서 만약 중간에 패킷이 소실되었다면 수신 측에서 처리한 마지막 패킷의 번호는 변동되지 않을 것이며 자연스럽게 ACK 번호 또한 변하지 않을 것이다.
즉, 동일한 ACK 신호를 가진 패킷이 여러 번 송신 측으로 보내질 수 있다는 것이다.
TCP 통신에서는 송신 측에서 3번이나 동일한 ACK 신호를 받았다면 어떠한 이유로 수신 측이 ACK 신호에 해당하는 패킷 이후의 패킷을 처리하지 못한 것으로 간주한다.
즉, TCP 통신 중 손실이 발생하여 통신 장애가 생겼다고 간주하는 것이다.
그렇다면 왜 3번일까?
TCP 통신의 특성상 패킷의 순서가 항상 유지될 것이라는 보장은 없다. 따라서 1~2번의 중복은 패킷의 순서가 뒤죽박죽으로 수신 측에 도착하였다고 생각하여 혼잡 상황으로 간주하지 않는 것이다.
3-ACK Duplicated 문제가 발생하여 통신 장애로 인해 송신되지 못한 패킷을 재전송하는 것을 "빠른 재전송"이라고 한다.
혼잡 제어에서는 빠른 재전송이 발생할 경우 혼잡이 발생한 것으로 간주하여 윈도우 사이즈를 절반으로 줄인다.
혼잡한 상태가 될 경우 윈도우 사이즈를 1로 줄이는 것이 아닌 절반으로 줄인 뒤 선형 증가시키는 방식이다.
빠른 회복 정책이 적용되었다면 혼잡 상황을 한 번 겪은 뒤 순수 AIMD 방식으로 동작하게 된다.
혼잡 제어 정책에는 Tahoe, Reno, New Reno, Cbuic, Elastic-TCP 등 다양한 정책이 존재한다.
혼잡 제어 정책은 모두 “혼잡이 발생하면 윈도우 크기를 줄이거나 증가시키지 않음으로써 혼잡을 회피한다”라는 전제 조건을 깔고 있으며, 이 방법을 어떻게 하면 효율적으로 구현할 수 있을까라는 고민에 위와 같은 다양한 방식이 존재하는 것이다.
모든 혼잡 제어 정책을 공부하는 데에는 한계가 있으므로 대표적인 TCP Tahoe와 TCP Reno 방식만 알아보자.
출처 : https://evan-moon.github.io/2019/11/26/tcp-congestion-control/
TCP Tahoe는 Slow Start를 사용한 혼잡 제어 초기 버전으로 빠른 재전송(Fast Transmit) 기법이 처음으로 도입된 방법이다.
TCP Tahoe에서는 첫 ssthresh(Threshold) 값을 송신 측 윈도우 크기의 절반으로 설정한다.
위 그래프에서 첫 Threshold가 8이므로 초기 송신 측 윈도우 크기는 16임을 유추할 수 있다.
이후 Slow Start 방식으로 윈도우 크기를 증가시키다 3-ACK Duplicated나 Timeout이 발생하면 사건이 발생했을 때의 윈도우 크기 절반으로 ssthreshold를 지정함과 동시에 윈도우 크기를 1로 감소시킨다.
즉, 이전 혼잡 상황을 기억하고 그 지점이 가까워지면 윈도우 크기를 조심스럽게 증가시키는 방식이다.
하지만 TCP Tahoe의 경우 Slow Start 구간에서 윈도우 크기를 1부터 증가시키므로 윈도우 크기를 키울 때 시간이 오래 걸리며 혼잡이 발생할 떄 윈도우 크기가 1이 되므로 비효율적인 방식이라고 할 수 있다.
따라서 TCP Tahoe에 빠른 회복(Fast Recovery)을 적용하여 이러한 문제점을 줄인 것이 TCP Reno이다.
출처 : https://evan-moon.github.io/2019/11/26/tcp-congestion-control/
TCP Reno는 TCP Tahoe와 동작 과정과 유사해 보이지만 매우 큰 차이점이 존재한다.
바로 “3 ACK Duplicated”와 “Timeout” 상황을 구분한다는 것이다.
Reno는 3 ACK Duplicated 때는 윈도우 크기를 반으로 줄이고 그 상황의 윈도우 사이즈 절반 값으로 Threshold 값을 변경시킨다. 위 이미지를 보면 6에서 3-ACK Duplicated가 발생했을 떄 Threshold는 3으로 지정되었으며 윈도우 크기도 3으로 반이 되었다.
또한 TCP Reno에서는 Timeout이 발생했을 때 윈도우 크기를 1로 줄여버리며 Threshold 값은 변경하지 않는다. 실제 위 그래프에서 Threshold는 3으로 유지되는 것을 볼 수 있다.
TCP Reno는 3-ACK Duplicated는 타임아웃에 비해 큰 혼잡이 아니라고 가정하여 나온 아이디어로 혼잡 상황의 경중을 따져 윈도우 크기 감소폭을 지정한다는 특징을 가진다.
TCP 통신에선 송/수신 동작의 효율을 높이기 위해 ACK 번호와 윈도우 크기를 통지하는 타이밍을 고려한다.
윈도우 크기는 수신 측이 수신 버퍼에서 데이터를 추출하여 애플리케이션에 건네주었을 때서야 알 수 있는 정보이다.
하지만 ACK 번호는 수신 측에서 데이터를 받은 뒤 정상 수신을 확인하면 바로 송신 측에 보내는 정보이다.
원래라면 값이 만들어지는 시기가 다르므로 ACK 번호와 윈도우 크기를 따로따로 보내야 하겠으나 이럴 경우 송신 측에 답변으로 보내는 패킷이 많아져 효율성이 저하될 것이다.
그래서 수신측은 ACK 번호나 윈도우를 통지할 때 소켓으로 패킷을 바로 보내지 않고 잠시 기다린다.
기다리는 사이 다음 통지 동작이 일어나면 생성된 정보를 한 개의 패킷으로 묶어 보낸다.
조금 어려울 수 있으니 예시를 들어보자.
1번 패킷 이후 2번 패킷이 보내진다고 가정하자. 1번 패킷이 수신 측에 도착했을 때 수신 측은 즉시 ACK 2를 가진 패킷을 생성한다. 하지만 이 패킷을 바로 송신 측에 보내지 않고 2번 패킷이 올 때까지 기다린다.
만약 2번 패킷이 도착하기 전 윈도우 크기까지 정해졌다면 ACK 2를 가진 패킷에 윈도우 크기까지 저장하여 송신 측에 보낼 것이다. 반대로 2번 패킷이 도착했는데 윈도우 크기가 정해지지 않았다면 그냥 ACK 2를 가진 패킷만 송신 측으로 보내지는 것이다.
즉, ACK 번호 송신을 대조할 때 윈도우 통지가 일어나면 ACK 번호와 윈도우를 한 개 패킷에 합승시켜 통지함으로써 네트워크를 흐르는 패킷의 양을 줄일 수 있는 것이다.