모두가 알다시피 네트워크는 꽤 불안전하다.
여전히 데이터는 손실되기도 하고, 엉뚱한 데이터를 주고받기도 하며, 송신자와 수신자가 서로를 영원히 기다리는 현상이 발생하기도 한다.
그러나 이런 상황에서 우리 프로그래머들은 걱정하지 않는다.
이유는 TCP가 데이터를 확실하게 주고 받을 수 있도록 해주기 때문이다.
이때, TCP가 해주는 것 중 하나가 바로 Flow Control 이다.
이 기능의 개념은 이렇다.
"데이터를 수신하는 노드가 전송하는 노드에게 현재 자신의 상태에 대한 정보를 보내주는 것이다."
지금 우리는 송신자의 데이터 전송 속도와 수신자의 데이터 처리 속도의 차이로 인한 문제에 집중해볼 것이다.
송신자의 데이터 전송 속도가 수신자의 데이터 처리 속도보다 느릴 경우에는 심각한 문제가 발생하지 않는다.
수신자가 데이터를 처리하고 대기하는 것이기에 자원을 낭비할 뿐이지 큰 문제가 발생하지는 않는다.
그러나 송신자의 데이터 전송 속도가 수신자의 데이터 처리 속도보다 빠를 경우에는 심각한 문제가 발생할 수 있다.
수신자가 데이터를 아직 처리하지 못했는데, 송신자는 계속해서 데이터를 전송한다.
물론 이런 경우를 대비해 수신자는 버퍼를 마련해서 데이터를 차곡차곡 저장한다.
그런데 만약 이 큐를 꽉 채우고도 남을 정도로 송신자가 데이터를 전송한다면 어떨까?
그러면 그냥 그대로 데이터를 잃어버리는 것이다.
그래서 우리는 데이터 손실을 없애야 한다 => 이를 위해 수신자가 자신의 상태를 송신자에게 알린다.
위 문제를 해결하기 위해서는 두 가지 방법이 있다.
Stop and Wait과 Sliding-Window 방식이다.
이 방법의 개념은 간단하다.
다만, 이 방법은 다음과 같은 문제가 발생한다.
그리고 다음과 같은 이유로 효율적이지 않다.
일정 시간 동안 한 개의 Frame 밖에 보내지 못한다.
그래서 이러한 효율성을 개선하고자 나온 방법이 Sliding-Window 방식이다.
시작 개념은 이렇다.
시간에 관계없이 갓 패킷에 번호를 붙여서 연속적으로 보내자!
먼저, 송신자(A)와 수신자(B)는 각자 버퍼를 준비한다.
A는 자신의 버퍼에 데이터를 쓰고, B는 자신의 버퍼에서 데이터를 읽어오는 것이다.
송신자A의 버퍼 상황이다.
A는 각 패킷에 번호를 매기고 패킷마다 Time을 건 다음 B에게 패킷을 전송한다.
위와 같은 상황에서 B가 3번 패킷을 받았다는 ack을 보내면 A는 8번 패킷을 전송한다.
만약 B가 자신의 RWS가 3,000 bytes라고 하면 A는 30개의 패킷을 전송한다.
Time 안에 각 패킷에 대한 ack이 오지 않으면 ack을 받지 못한 패킷에 대해 재전송을 한다.
A는 자신이 전송한 가장 마지막 순서 패킷의 번호와 가장 최근에 받은 ack의 번호를 기억한다.
=> 위 그림의 경우 2번은 A가 가장 최근에 받은 ACK 패킷의 번호이고,
7번은 A가 전송한 패킷 중 가장 마지막 순서 패킷의 번호이다.
B의 데이터를 읽는 속도가 떨어질 경우, WS(Window Size)를 줄여가며 송신자의 데이터 전송을 컨트롤할 수 있다.
송신자의 상황에 맞게 데이터를 전송하여 무의미한 데이터 전송을 방지할 수 있게 된 것이다.