호우동의 개발일지

Today :

article thumbnail

흐름 제어 서비스(flow-control service)


애플리케이션에게 흐름 제어 서비스를 제공하는 이유

  • TCP 연결의 각 종단에서 호스트들은 연결에 대한 개별 수신 버퍼를 설정
    송신자는 수신자의 버퍼를 오버플로시키는 것을 방지하기 위해 제공

    • 수신자의 버퍼가 오버플로가 발생하는 과정
      1. TCP 연결이 순서대로 올바르게 바이트를 수신할 때 TCP는 데이터를 수신 버퍼에 저장
      2. 해당 애플리케이션 프로세스는 버퍼에서 데이터를 읽지만, 수신한 시점에 읽을 필요 없음
        → 오랜 시간 동안 데이터를 읽지 않을 수도 있음

      3. 송신자가 점점 더 많은 데이터를 전송함으로써 연결의 수신 버퍼에 오버플로 발생
        • 애플리케이션이 데이터 읽는 속도가 느릴수록 발생 가능성 높음
        • 송신자의 데이터 전송 속도가 빠를수록 발생 가능성 높음

 


흐름제어와 혼잡제어

  • 흐름 제어 : 수신하는 애플리케이션이 읽는 속도와 송신자가 전송하는 속도를 일치시키는 서비스
  • TCP 송신자는 혼잡 제어(congestion control) 될 수 있다.
    • TCP 송신자는 IP 네트워크에서 혼잡 때문에 억제될 수 있다.

  • 흐름 제어와 혼잡 제어는 수행되는 동작이 비슷하지만, 명백히 각기 다른 목적으로 수행된다.

 

 


TCP가 흐름제어 서비스를 제공하는 방법

  • 여기서의 TCP 구현은 TCP 수신자가 순서가 바뀐 세그먼트를 버린다고 가정


수신 윈도(receive window)

  • TCP는 송신자가 수신 윈도라는 변수를 유지하여 흐름 제어를 제공한다.
  • 수신 윈도는 수신 측에서 가용한 버퍼 공간이 얼마나 되는지 송신자에게 알려주는 데 사용
  • TCP는 전이중이므로 연결의 각 측의 송신자는 별개의 수신 윈도를 유지

 


파일 전송 환경에서 수신 윈도 동작

수신 윈도와 수신 버퍼
수신 윈도와 수신 버퍼

  • 가정 : TCP 연결상에서 호스트 A가 호스트 B에게 큰 파일을 전송한다고 가정
  1. 호스트 B는 이 연결에 수신 버퍼를 할당
    → 이때 할당된 수신 버퍼의 크기를 RcvBuffer라고 명명

  2. 호스트 B의 애플리케이션 프로세스는 버퍼로부터 데이터를 읽으며 아래의 변수들을 정의한다.

정의되는 변수들

  • LastByteRead
    • B의 애플리케이션 프로세스에 의해 버퍼로부터 읽힌 데이터 스트림의 마지막 바이트의 번호

  • LastByteRcvd
    • B에서 네트워크로부터 도착하여 수신 버퍼에 저장된 데이터 스트림의 마지막 바이트가 의 번호

  • TCP는 할당된 버퍼의 오버플로를 허용하지 않으므로 다음 수식이 가능
    • LastByteRcvd - LastByteReadRcvBuffer

  • rwnd(수신 윈도)는 버퍼의 여유 공간으로 설정된다.
    • rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
    • 시간에 따라 여유 공간은 변하기 때문에 rwnd는 동적이다.

흐름 제어 서비스를 제공하기 위한 변수 rwnd의 사용

  • 호스트 B는 A에게 전송하는 모든 세그먼트의 윈도 필드를 현재의 rwnd 값으로 설정
    → 이를 통해 연결 버퍼에 얼마만큼의 여유 공간이 있는지를 호스트 A에게 알려준다.

  • 초기에는 호스트 B가 rwnd = RcvBuffer로 설정
    • 이를 성사시키기 위해, 호스트 B는 몇 개의 특정 연결 관련 변수들을 유지해야 함

LastByteSent와 LastByteAcked

  • 호스트 A는 명백히 의미가 있는 두 변수 LastByteSentLastByteAcked를 유지
  • (LastByteSent - LastByteAcked) = A가 이 연결에 전송 확인 응답이 안된 데이터의 양
    • rwnd의 값보다 작은 값으로 유지함으로써 A는 B의 수신 버퍼에 오버플로 발생하지 않음을 확신
      → 호스트 A는 연결된 동안 LastByteSent - LastByteAcked ≤ rwnd를 보장

 


흐름 제어의 기술적인 문제

  • 가정
    • 호스트 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가 세그먼트를 읽는 과정

  1. UDP는 대응하는 소켓 앞에 위치한 유한 크기 버퍼에 세그먼트를 쌓는다.
  2. 프로세스는 버퍼로부터 한 번에 하나의 전체 세그먼트를 읽는다.
  3. 프로세스가 버퍼로부터 매우 빠르게 세그먼트를 읽지 못하면,
    버퍼는 오버플로 될 것이고 세그먼트를 잃어버릴 것이다.