흐름 제어 서비스(flow-control service)
애플리케이션에게 흐름 제어 서비스를 제공하는 이유
- TCP 연결의 각 종단에서 호스트들은 연결에 대한 개별 수신 버퍼를 설정
→ 송신자는 수신자의 버퍼를 오버플로시키는 것을 방지하기 위해 제공
- 수신자의 버퍼가 오버플로가 발생하는 과정
- TCP 연결이 순서대로 올바르게 바이트를 수신할 때 TCP는 데이터를 수신 버퍼에 저장
- 해당 애플리케이션 프로세스는 버퍼에서 데이터를 읽지만, 수신한 시점에 읽을 필요 없음
→ 오랜 시간 동안 데이터를 읽지 않을 수도 있음 - 송신자가 점점 더 많은 데이터를 전송함으로써 연결의 수신 버퍼에 오버플로 발생
- 애플리케이션이 데이터 읽는 속도가 느릴수록 발생 가능성 높음
- 송신자의 데이터 전송 속도가 빠를수록 발생 가능성 높음
- 수신자의 버퍼가 오버플로가 발생하는 과정
흐름제어와 혼잡제어
- 흐름 제어 : 수신하는 애플리케이션이 읽는 속도와 송신자가 전송하는 속도를 일치시키는 서비스
- TCP 송신자는
혼잡 제어(congestion control)
될 수 있다.- TCP 송신자는 IP 네트워크에서 혼잡 때문에 억제될 수 있다.
- TCP 송신자는 IP 네트워크에서 혼잡 때문에 억제될 수 있다.
- 흐름 제어와 혼잡 제어는 수행되는 동작이 비슷하지만, 명백히 각기 다른 목적으로 수행된다.
TCP가 흐름제어 서비스를 제공하는 방법
- 여기서의 TCP 구현은 TCP 수신자가 순서가 바뀐 세그먼트를 버린다고 가정
수신 윈도(receive window)
- TCP는 송신자가
수신 윈도라는
변수를 유지하여 흐름 제어를 제공한다. - 수신 윈도는 수신 측에서 가용한 버퍼 공간이 얼마나 되는지 송신자에게 알려주는 데 사용
- TCP는 전이중이므로 연결의 각 측의 송신자는 별개의 수신 윈도를 유지
파일 전송 환경에서 수신 윈도 동작
- 가정 : TCP 연결상에서 호스트 A가 호스트 B에게 큰 파일을 전송한다고 가정
- 호스트 B는 이 연결에 수신 버퍼를 할당
→ 이때 할당된 수신 버퍼의 크기를RcvBuffer
라고 명명 - 호스트 B의 애플리케이션 프로세스는 버퍼로부터 데이터를 읽으며 아래의 변수들을 정의한다.
정의되는 변수들
LastByteRead
- B의 애플리케이션 프로세스에 의해 버퍼로부터 읽힌 데이터 스트림의 마지막 바이트의 번호
- B의 애플리케이션 프로세스에 의해 버퍼로부터 읽힌 데이터 스트림의 마지막 바이트의 번호
LastByteRcvd
- B에서 네트워크로부터 도착하여 수신 버퍼에 저장된 데이터 스트림의 마지막 바이트가 의 번호
- B에서 네트워크로부터 도착하여 수신 버퍼에 저장된 데이터 스트림의 마지막 바이트가 의 번호
- TCP는 할당된 버퍼의 오버플로를 허용하지 않으므로 다음 수식이 가능
LastByteRcvd
-LastByteRead
≤RcvBuffer
rwnd(수신 윈도)는
버퍼의 여유 공간으로 설정된다.rwnd
=RcvBuffer
- [LastByteRcvd
-LastByteRead
]- 시간에 따라 여유 공간은 변하기 때문에 rwnd는 동적이다.
흐름 제어 서비스를 제공하기 위한 변수 rwnd의 사용
- 호스트 B는 A에게 전송하는 모든 세그먼트의 윈도 필드를 현재의 rwnd 값으로 설정
→ 이를 통해 연결 버퍼에 얼마만큼의 여유 공간이 있는지를 호스트 A에게 알려준다. - 초기에는 호스트 B가
rwnd
=RcvBuffer로
설정- 이를 성사시키기 위해, 호스트 B는 몇 개의 특정 연결 관련 변수들을 유지해야 함
- 이를 성사시키기 위해, 호스트 B는 몇 개의 특정 연결 관련 변수들을 유지해야 함
LastByteSent와 LastByteAcked
- 호스트 A는 명백히 의미가 있는 두 변수
LastByteSent
와LastByteAcked
를 유지 - (
LastByteSent
-LastByteAcked
) = A가 이 연결에 전송 확인 응답이 안된 데이터의 양- rwnd의 값보다 작은 값으로 유지함으로써 A는 B의 수신 버퍼에 오버플로 발생하지 않음을 확신
→ 호스트 A는 연결된 동안LastByteSent - LastByteAcked ≤ rwnd를
보장
- rwnd의 값보다 작은 값으로 유지함으로써 A는 B의 수신 버퍼에 오버플로 발생하지 않음을 확신
흐름 제어의 기술적인 문제
- 가정
- 호스트 B 수신버퍼는 rwnd = 0으로 가득 찼다고 가정
- 호스트 A에게 rwnd = 0이라고 알린 후, 호스트 B는 A에게 전송할 게 없다고 가정
발생하는 현상
- 호스트 B의 애플리케이션 프로세스가 버퍼를 비워도,
TCP는 호스트 A에게 새로운 rwnd로 새로운 세그먼트를 전송하지 않는다. - TCP는 전송할 데이터가 있거나 전송할 확인응답을 가진 경우에만 A에게 세그먼트 전송
→ 호스트 A는 B의 수신 버퍼에 약간의 공간이 있다는 것을 모른다.
→ 호스트 A는 차단되고 더는 데이터를 전송할 수 없다.
문제 해결법
- TCP 명세서는 호스트 A가 B의 수신 윈도가 0일 때,
- 1바이트 데이터로 세그먼트를 계속해서 전송하도록 요구
- 이 세그먼트들은 수신자에 의해 긍정 확인응답될 것이다.
- 이 세그먼트들은 수신자에 의해 긍정 확인응답될 것이다.
- 결과적으로 버퍼는 비워지고 긍정 확인응답은 0이 아닌 rwnd 값을 포함한다.
UDP가 흐름 제어를 제공하지 않는 이유
- 가정 - 호스트 A의 한 프로세스가 호스트 B의 프로세스에게 연속적인 UDP 세그먼트 전송
UDP가 세그먼트를 읽는 과정
- UDP는 대응하는 소켓 앞에 위치한 유한 크기 버퍼에 세그먼트를 쌓는다.
- 프로세스는 버퍼로부터 한 번에 하나의 전체 세그먼트를 읽는다.
- 프로세스가 버퍼로부터 매우 빠르게 세그먼트를 읽지 못하면,
버퍼는 오버플로 될 것이고 세그먼트를 잃어버릴 것이다.