호우동의 개발일지

Today :

article thumbnail

신뢰적인 데이터 전송


비신뢰적인 인터넷의 네트워크 계층(IP 서비스)

  • 인터넷 프로토콜은 데이터그램 전달을 보장 X
  • 데이터그램이 순서대로 전달되는 것도 보장 X
  • 데이터그램에 포함된 데이터의 무결성(intergrity)을 보장 X
    • 비트가 손상될 수도 있다.

  • IP 서비스에서 데이터그램은 라우터의 버퍼를 오버플로 상태로 만들 수 있음
  • 트랜스포트 계층의 세그먼트가 IP 데이터그램에 의해 네트워크 상에서 운반됨
    → 트랜스포트 계층의 세그먼트도 이러한 문제를 겪을 수 있음

 


TCP의 신뢰적인 데이터 전송 서비스

  • TCP는 IP의 비신뢰적인 최선형 서비스에서 신뢰적인 데이터 전송 서비스를 제공
  • TCP 타이머 관리 절차에서는 단일 재전송 타이머 사용을 권장한다.
    • 전송됐지만 아직 확인응답받지 못한 세그먼트와 개별적인 타이머가 한쌍인 경우
      → 이론상으론 좋아도, 타이머 관리는 상당한 오버헤드를 발생시킨다.

    • 이 글에서는 단일 타이머 사용을 전제로 한다.

 

신뢰적인 데이터 전송 서비스의 사용

  • 프로세스가 자신의 수신 버퍼로부터 읽은 데이터 스트림이 손상/손실/중복이 없다는 것을 보장
  • 자신의 수신 버퍼로부터 읽은 데이터 스트림이 순서가 유지된다는 것을 보장한다.
  • 바이트 스트림은 송신자가 전송한 것과 같은 바이트 스트림
    → 신뢰적인 데이터 전송의 원칙을 모두 포함한다.

 

 


TCP 신뢰적인 데이터 전송과 관련된 3가지 주요 이벤트

/* 
송신자가 TCP 흐름이나, 혼잡 제어로 인해 제한받지 않는다고 가정하고,
위의 데이터의 크기는 MSS보다 작고, 데이터 전송한 한 방향이라고 가정한다.
*/

NextSeqNum=InitialSeqNumber
SendBase=InitialSeqNumber

loop (forever) {
        switch(event)

                event: data received from application above
                        create TCP segment with sequence number NextSeqNum
                        if(timer currently not running)
                                start timer
                        pass segment to IP
                        NextSeqNum=NextSeqNum+length(data)
                        break;

                event: timer timeout
                        retransmit not-yet-acknowledged segment with
                                smallest sequence number
                        start timer
                        break;

                event: ACK received, with ACK field value of y
                        if(y > SendBase) {
                                SendBase = y
                                if(there are currently any not-yet-acknowledged segments)
                                        start timer
                                }
                        break;

}    /* 무한 루프 종료 */
  • 가정
    • 호스트 A에서 B로 데이터가 오직 한 방향으로만 보내짐
    • 호스트 A가 큰 파일을 전송

  • 해당 코드에서 데이터 전송/재전송에 관련된 세 가지 주요 이벤트가 있음
    상위 애플리케이션으로부터 수신된 데이터, 타이머 타임아웃, ACK 수신

 


첫 번째 주요 이벤트 - 상위 애플리케이션으로부터 수신된 데이터

  • TCP는 애플리케이션으로부터 데이터를 받음
  • 세그먼트는 받은 데이터를 캡슐화하고 IP에게 해당 세그먼트를 넘김
    • 각 세그먼트는 해당 세그먼트의 순서 번호 포함한다.

  • 타이머가 이미 다른 세그먼트에 대해 실행 중이 아닌 경우
    → TCP는 이 세그먼트를 IP로 넘길 때 타이머를 시작
    • 이 타이머의 만료 주기는 TimeoutInterval

 


두 번째 주요 이벤트 - 타임아웃

  • TCP는 타임아웃 이벤트에 대해 타임아웃을 일으킨 세그먼트를 재전송하여 응답
  • TCP의 타이머를 재시작

 


세 번째 주요 이벤트 - 수신자로부터의 수신 확인응답 세그먼트(ACK) 수신

  • 여기서 수신자는 다양한 ACK 필드값을 가진 세그먼트를 뜻함
  • 이 이벤트가 발생하면 TCP 변수 SendBase와 ACK 값 y를 비교
    • SendBase : 수신 확인응답이 확인되지 않은 가장 오래된 바이트의 순서 번호
      • SendBase-1 은 수신자에게서 차례대로 수신됐음을 알리는 마지막 바이트 순서 번호

    • TCP는 누적 확인응답을 사용
    • y는 y 바이트 이전의 모든 바이트의 수신 확인

  • y > SendBase 인 경우
    • ACK는 이전에 확인응답 안 된 하나 이상의 세그먼트들을 확인
      → 송신자는 자신의 SendBase 변수를 갱신

    • 또한 아직 확인응답 안 된 세그먼트들이 존재한다면 타이머를 재시작

 

신뢰적인 데이터 전송이 작동하는 과정 - 시나리오 1

손실된 확인응답에 기인하는 재전송
손실된 확인응답에 기인하는 재전송

 

  • 가정
    • 긍정 확인응답이 손실됐을 때
    • 호스트 A가 호스트 B에게 하나의 세그먼트를 보냄
    • 이 세그먼트는 순서 번호 92와 8바이트의 데이터를 포함한다고 가정

  • 과정
  1. 호스트 A가 해당 세그먼트 전송 후
    → 호스트 B로부터 긍정 확인응답 번호 100을 가진 세그먼트를 기다림

  2. B가 수신하고 A로 긍정 확인응답 번호 100 (ACK = 100) 전송
  3. 이때 ACK= 100이 손실된다고 가정
  4. 타임아웃이 발생하고, 호스트 A는 같은 세그먼트를 B에게 재전송
  5. 호스트 B가 재전송 세그먼트를 수신했을 때, 이미 수신된 데이터임을 알 수 있음
    ← 재전송된 세그먼트가 포함하고 있는 순서 번호를 통해 알 수 있기 때문

  6. 호스트 B는 이미 수신된 데이터이므로, 재송신된 세그먼트의 바이트를 버림

 

신뢰적인 데이터 전송이 작동하는 과정 - 시나리오 2

세그먼트 100이 재전송되지않는 경우
세그먼트 100이 재전송되지 않는 경우

  • 가정
    • 호스트 A가 연속해서 2개의 세그먼트를 전송
      • 첫 번째 세그먼트 → 순서 번호 92와 8바이트의 데이터를 가짐
      • 두 번째 세그먼트 → 순서 번호 100과 20바이트의 데이터를 가짐

    • 두 세그먼트가 모두 호스트 B에 무사히 도착한다고 가정
    • 호스트 A에서는 타임아웃 이전에 어떠한 긍정 확인응답도 수신하지 못한다고 가정

  • 과정
    1. B는 각각의 세그먼트에 대해 2개의 개별적인 긍정 확인응답을 전달
      • 첫 번째 → 긍정 확인응답 번호 100(ACK = 100)을 가짐
      • 두 번째 → 확인응답 번호 120(ACK = 120)

    2. 호스트 A에서 타임아웃 이벤트가 발생
      → 순서 번호 92로 첫 번째 세그먼트를 재전송하고 타이머를 재시작
      • 새로운 타임아웃이 끝나기 전까진 두 번째 세그먼트의 ACK = 120가 도착해도 재전송 X

 

신뢰적인 데이터 전송이 작동하는 과정 - 시나리오 3

누적 확인응답은 첫번째 세그먼트의 재전송을 방지한다.
누적 확인응답은 첫번째 세그먼트의 재전송을 방지한다.

  • 가정
    • 호스트 A가 2개의 세그먼트를 전송한다고 가정
    • 첫 번째 세그먼트의 긍정 확인응답이 네트워크에서 분실된다고 가정

  • 과정
    1. 첫 번째 세그먼트의 긍정 확인응답이 네트워크에서 분실
    2. 첫 번째 세그먼트의 타임아웃 전에 호스트 A가 ACK=120을 수신
      → 호스트 B가 119 바이트까지 모든 데이터를 수신했음을 알게 됨

    3. 호스트 A는 두 세그먼트 중 어떠한 것도 전송하지 않는다.

  • 누적 확인응답은 첫 번째 세그먼트의 재전송을 방지한다.

 


빠른 재전송

타임아웃이 유발하는 재전송 문제

  • 타임아웃의 주기가 때때로 비교적 길다는 점
  • 긴 타임아웃 주기는 잃어버린 패킷을 다시 보내기 전에 송신자를 오래 기다리게 한다.
    긴 타임아웃 주기는 종단 간의 지연을 증가시킨다.

  • 다행히, 송신자는 종종 중복 ACK에 의한 타임아웃이 일어나기 전에 패킷 손실을 발견
    • 중복 ACK : 송신자가 이미 이전에 받은 확인응답에 대한 재확인응답 세그먼트 ACK

 

수신자가 중복 ACK를 보내는 이유

  • TCP 수신자가 기다리는 다음 것보다 더 큰 순서 번호를 가진 세그먼트를 받은 경우
    → TCP 수신자는 그 데이터 스트림에서의 간격(손실 세그먼트)을 찾아냄

    • 여기서의 간격은 세그먼트 손실이나, 순서가 바뀐 결과일 수도 있다.

  • TCP는 부정 확인응답을 사용 X
    → 수신자는 마지막으로 수신된 순차적인 바이트를 갖는 데이터를 다시 확인응답(즉, 중복 ACK 생성)

    • 수신자가 순서가 뒤바뀐 세그먼트를 버리지 않는 경우라고 가정

 

중복 ACK에 대한 송신자의 반응

  • 송신자는 많은 양의 세그먼트를 연속적으로 보낼 수 있음
    → 하나의 세그먼트를 잃어버린다면 많은 연속적인 중복 ACK 존재 가능

  • TCP 송신자가 같은 데이터에 대해 3개의 중복 확인응답을 수신
    → ACK 된 세그먼트의 다음 3개의 세그먼트가 분실되었음을 의미

    • 3개의 중복 ACK를 수신할 때, TCP는 빠른 재전송
      • 빠른 재전송 : 세그먼트의 타이머가 만료되기 전에 손실 세그먼트를 재전송

빠른 재전송 : 세그먼트의 타이머가 초과되기 전에 손실된 세그먼트 재전송
빠른 재전송: 세그먼트의 타이머가 초과되기 전에 손실된 세그먼트 재전송

  • 두 번째 세그먼트를 잃어버린 경우, 타이머가 만료되기 전에 재전송됨
event : ACK received, with ACK field value of y
                            if(y > SendBase) {
                            SendBase = y
                            if(these are currently any not yet acknowledged segments)
                                    start timer
                            }
                            else { /* 이미 ACK된 세그먼트에 대한 중복 ACK*/
                                        increment number of duplicate ACKs received for y
                                        if(number of duplicate ACKs received for y == 3)
                                            /* TCP 빠른 재전송 */
                                            resend segment with sequence number y
                            }
                    break;

 


TCP는 GBN인가? SR인가?

  • TCP 확인응답은 누적되고 올바르게 수신된다.
    • 순서가 잘못된 세그먼트는 수신자가 개별적으로 ACK를 받지 않는다.
    • TCP 송신자는 SendBaseNextSeqNum를 유지해야 한다.
      • SendBase : 전송했지만 확인응답 안 된 바이트의 가장 작은 순서 번호
      • NextSeqNum : 전송될 다음 바이트의 순서 번호

      → 이런 관점에서는 GBN 형태의 프로토콜과 비슷해 보이지만, 차이점이 존재

 

TCP와 GBN의 차이점

  • TCP는 올바르게 수신되었지만 순서가 바뀐 세그먼트들을 버퍼링 한다.
  • 예시
    • 가정
      • 송신자가 세그먼트 1,2…N을 전송하고 수신 측에 오류 없이 순서대로 도달
      • 패킷 n < N에 대한 긍정 확인응답이 손실됐음
      • 하지만, 나머지 N-1개의 긍정 확인응답들은 타임아웃 전에 송신 측에 도달

    • GBN의 동작
      • 패킷 n과 n+1, n+2 … N 모두를 재전송한다.

    • TCP의 동작
      • 세그먼트 n 하나만을 재전송한다.
      • 세그먼트 n에 대한 타임아웃 전에 세그먼트 n+1에 대한 긍정 확인응답이 도착할 경우
        → 세그먼트 재전송 X

 

선택적 확인응답(selective acknowledgement)

  • TCP에 수정 제안된 것
  • TCP 수신자가 ‘순서가 틀린’ 세그먼트에 대해 선택적으로 확인응답을 하게 한다.
    • 기존에는 올바르게 수신된 ‘순서가 맞는’ 세그먼트에 대해 확인응답하였음

  • 선택적 재전송과 결합했을 경우
    → TCP는 원래의 SR 프로토콜과 유사

 

결론

  • TCP의 오류 복구 메커니즘은 GBN과 SR 프로토콜의 혼합으로 분류하는 것이 적당