컴퓨터네트워크

컴퓨터네트워크_3.5~7 TCP

강용민 2021. 11. 7. 21:14

연결기반 트랜스포트 : TCP

TCP의 특징을 먼저 알아보자

  • 점대점(point to point)
    • 단일 송신자와 단일 수신자의 통신이다.
  • 신뢰적인 순차 바이트 스트림(reliable, in-order byte stream)
    • 메시지의 경계가 없다.
  • 파이프라인(pipelined)
    • stop&wait의 반대 방식으로 특정량(윈도우)만큼의 메시지를 연속적으로 보낸다.
    • 더보기
      stop&wait의 방식은 하나의 메시지를 보내면 receiver측에서 받았다는 메시지가 오기 전까지 다음 메시지를 보내지 않는다.
    • TCP 혼잡 및 흐름제어에서 윈도우 크기를 결정한다.
  • 전 이중 데이터(full duplex data)
    • 한 개의 연결에서 양방향 데이터 흐름을 가진다.
    • MSS(maximum segment size) : 최대 세그먼트 크기
  • 연결지향형(connection oriented)
    • 데이터 교환 전에 송수신자 간에 제어 메시지 교환을 한다.(즉, 핸드쉐이킹을 한다.)
  • 흐름 제어(flow control)
    • 송신자는 수진자의 버퍼 한계를 초과하여 전송하지 않는다.

TCP 세그먼트의 구조

source port #(출발지를 알려줄 때 필요) dest port#(목적지로 갈 때 필요)
sequence number(순서대로 잘 갔는지 확인할 때 필요)
acknowledgement number(순서대로 잘 받았는지 확인할 때 필요)
head len, U,A,P,R,S,F receive window (흐름 제어할 때 필요)
checksum(bit error 점검 시 필요) Urg data pointer
options(variable length)
application data
더보기

UDP 세그먼트 구조

source port # dest port #
length checksum
application data

TCP에 비해 세그먼트구조가 간단하다.

순서 번호(sequence number)

송신자의 송신 세그먼트에서 전송되는 데이터의 시작 순서 번호를 세그먼트에 포함한다.

ACK 번호(ackowledgement number)

수신자로부터 송신자가 직전에 정상 수신한 세그먼트의 데이터의 마지막 번호 다음 번호를 세그먼트에 포함한다.

 

예를들어 Host A가 Host B에게 어떤 정보를 수신하려한다고 치자.

그럼 Host A는 sequence number를 세그먼트에 넣어 보낼 것이다. 임의로 sequence number = 42라고 하자.

그럼 Host B는 해당 세그먼트를 받고 ackowledgement number로 sequence number의 다음 숫자. 즉, 43을 포함한 세그먼트를 보낼 것 이다.

 

TCP 왕복시간과 타임아웃

이전에 rdt 3.0까지 알아봤는데, 특징으로 메시지를 송수신할 때 타이머를 이용한다는 것을 배웠다.

이번에는 그 타이머(TCP 타임아웃)값을 어떻게 설정하는가를 보려한다.

당연히 RTT보다는 커야한다. 타임아웃시간이 RTT보다 작다면 잦은 타임아웃이 생기고 그로인해 불필요한 재전송이 계속 생기기 때문이다.

반대로 RTT보다 너무 크다면, 예를들어 2RTT의 값을 준다면 세그먼트 손실확인이 늦어 세그먼트 손실 대응이 지연된다.

 

그래서 적당한 타임아웃시간을 정해야하는데 정하기 전에 RTT값을 알아야한다.

RTT값을 측정은 SampleRTT값을 이용해 EstimatedRTT를 구하여 측정한다.

SampleRTT는 샘플 세그먼트 송신 후 ACK를 받기까지 측정된 시간을 뜻한다.

식은 EstimatedRTT = (1 - a)* EstimatedRTT + a*sampleRTT 이다. a는 일반적으로 0.125값이다.

EstimatedRTT를 구했으나 EstimatedRTT를 타임아웃값으로 한다면 EstimatedRTT보다 더 시간이 걸린 RTT는 모두 타임아웃이된다. 위 그림을 보면 sampleRTT의 반정도가 EstimatedRTT보다  높다.

그래서 EstimateRTT에 어느정도의 변동폭을 책임질 안전한 마진이 필요하다

식은 DevRTT = (1-B) * DevRTT + B * |SampleRTT - EstimatedRTT|이다. B는 일반적으로 0.25이다.그래서 총 RTT값. TimeoutInterval 은 EstimatedRTT + 4*DevRTT이다.

 

신뢰적인 데이터 전송

TCP는 IP의 비신뢰적 서비스 상에 신뢰적 서비스를 제공해줘야 한다.

재전송을 통해 데이터가 확실히 전달되도록 하는데 재전송을하는 경우는 두가지이다.

  • 타임아웃 이벤트(Timeout)
  • 중복 ACK(duplicate ACK)

TCP 송신자 이벤트

  1. 어플리케이션으로부터 데이터 수신(data receive from application above)
    1. 순서번호(sequance number)를 포함한 세그먼트를 생성한다.
    2. 순서번호는 세그먼트에서 첫 번째 바이트의 스트림 번호이다.
    3. 타이머가 동작하고 있지 않으면 타이머 시작한다.
      1. 타이머는 가장 오래되고 ACK 미수신된 세그먼트를 대상으로 한다.
      2. 만료 간격 : TimeOutInterval
  2. 타임아웃
    1. 타임아웃 유발한 세그먼트를 재전송한다.
    2. 타이머 재시작
  3. ACK 수신
    1. 이전에 ACK 수신하지 못한 세그먼트의 ACK라면
      1. 세그먼트를 ACK응답으로 표시
      2. 아직 ACK 받지 못한 세그먼트가 있으면 타이머 시작

TCP ACK 생성과정

수신자 이벤트 TCP 수신자 동작
기다리는 순서번호를 가진 순서에 맞는 세그먼트 도착.
이 순서 번호 이전까지의 모든 데이터 수신
지연된 ACK. 다음 순서의 세그먼트 도착을 위해 500ms까지 기다림.
만약 다음 세그먼트가 이 기간 내 도착하지 않으면 ACK를 보냄
기다리는 순서번호를 가진 순서에 맞는 세그먼트의 도착.
ACK 전송을 준비하는 다른 세그먼트 있음
즉시 두 개의 순서에 맞는 세그먼트들에 대한 하나의 누적 ACK를 전송
기다리는 것 보다 높은 순서번호를 갖는 순서가 틀린 세그먼트의 도착. 간격(gap)이 감지됨 즉시 기다리는 바이트의 순서번호(간격의 최저값)를 나타내는 중복 ACK를 전송
간격을 부분적으로 또는 모두 채우는 세그먼트 도착 간격의 최저값분터 세그먼트가 시작된다면 즉시 ACK를 전송

 

TCP 빠른 재전송(Fast retransmit)

아까 TimeoutInterver이 크면 손실된 패킷을 다시 보내기 전까지 오래 기다린다는 것을 알아보았다.

그래서 TCP 재전송 기법 중 빠른 재전송 기법을 알아보려한다.

TCP 빠른 재전송 기법은 중복 ACK를 통해 손실된 세그먼트를 감지한다.

송신자는 여러 개의 세그먼트를 순차 송신하고, 수신자는 동일한 세그먼트 수신되면 중복 ACK 회신하는 것을 이용하여 송신자가 수신자로부터 같은 패킷에 대한 3개 중복 ACK를 수신하게 되면 ACK 응답된 세그먼트의 다음 세그먼트가 손실되었다고 가정하여 타이머가 만료되기도 전에 재전송을 한다.

 

흐름제어(flow control)

흐름제어는 수신자가 송신자를 제어하여, 수신자의 수신 버퍼의 여유 공간 이상으로 과도하거나 빠르게 데이터를 전송하지 못하도록 제어하는 것이다.

흐름제어는 congestion control과는 다르다. 흐름제어는 각 센더와 리시버 사이의 시스템 사이의 문제이나 congestion control은 네트워크상의 문제이다.

원리는 다음과 같다.

  1. 수신자는 수신 여유 공간 크기인 rwnd 값을 TCP 헤더 필드를 통해 송신자에게 전달한다.
  2. 송신자는 수신자의 rwnd 값 이하로 송신 데이터 크기를 제한한다.
  3. 그리하여 송신자는 수신자 버퍼가 오버플로우가 되지 않도록 보장하는 것이다.

 

연결 관리

TCP는 데이터를 교환하기 전에 송수신자 간에 핸드쉐이킹을 한다.

핸드쉐이킹은 횟수로 단계를 나눌 수 있다.

2단계 핸드쉐이크는 원리는 다음과 같다.

  1. sender에서 연결요청을 보낸다.
  2. receiver은 연결요청을 받으면 연결확인을 보낸다.

다만 문제점은 송수신간의 RTT보다 타임아웃이 더 빠른경우 재전송이 일어나는데 그 재전송하는 동안에 연결이 종료되어 세그먼트가 중간에 길을 잃을 수 있다.

3단계 핸드쉐이크의 원리는 다음과 같다.

  1. sender에서 SYNbit를 1로보낸다.
  2. receiver에서는 SYNbit를 1로 받으면 SYNbit와 ACKbit를 1로 보낸다.
  3. sender에서 ACKbit를 1로 받으면 reveiver에게 다시 ACKbit =1 로 보내고 연결되었다는 상태를 취한다.
  4. revceiver은 ACKbit를 받고 연결되었다는 상태를 취한다.

핸드쉐이킹 방식을 알았으니 이번에는 연결을 종료하는 방법을 알아보자.

  1. 종료를 할 쪽에서 FIN비트를 1로 하여 상대방에게 TCP 세그먼트를 전송한다.
  2. 상대방은 FIN비트를 수신하면 ACK를 보낸쪽에게 전송하고, 아직 전송되지 않은 데이터들을 다 전송을 한다.
  3. 데이터를 다 전송했으면, FIN비트를 1로 하여 보낸쪽에게 전송한다.
  4. FIN비트를 받으면 ACK비트를 보내고 일정시간을 기다린다.
    1. max segment lifetime의 2배의 시간을 기다리는데 혹시 ACK가 중간에 소실될 경우를 대비한 것으로 다시 FIN이 왔을경우 다시 ACK을 보내야한다.

혼잡제어(congestion control)

혼잡제어는 네트워크가 처리하지 못 할 수준으로 여러 발신지에서 많은 데이터를 전송할 때를 제어하는 것이다.

 

먼저 AIMD(additive increase multiplicative decrease)방식에 대해 알아보자.

AIMD는 송신자는 손실 발생할 때까지 매 RTT 마다 1MMS 단위로 cwnd(congestion window)를 증가시킨다.

만약 손실이나 타임아웃의 경우 cwnd를 반으로 감소시킨다. 이것을 RENO감소라 한다.

TCP 전송율은 cwnd/RTT가 된다.

 

이번엔 슬로우 스타트방식을 알아볼 것이다.

슬로우 스타트 방식은 연결되면 초기 cwnd은 1MSS로 시작을 하여 손실 발생 전까지  매 RTT마다(매 ACK수신될 때마다)cwnd를 2배씩 증가 시킨다.

만약 손실이나 타임아웃의 경우 cwnd를 다시 1MSS로 설정하여 임계점(ssthresh)까지는 다시 지수적으로 증가하다 임계점에 다다르면 선형적으로 증가한다. 이방식은 Tahoe감소라 한다.'

 

TCP는 처음에 슬로우 스타트로 시작을 하다 임계점을 넘어가면 CA(Congestion avoidance)로 넘어간다.

  • CA로 하는 중에 중복된ACK를 3번이상 받으면 임계점을 cwnd의 반으로 설정하고 swnd는 변한 임계점에 +3부터 다시 시작한다.
  • CA로 하는 중에 타임아웃이 되면 임계점을 cwnd의 반으로 설정하고 cwnd를 1부터 다시 시작한다.

TCP 공평성

---