본문 바로가기
네트워크

연결지향형 트랜스포트 : TCP

by SpearZero 2024. 2. 14.

TCP는 신뢰적인 데이터 전송을 제공하기 위해 오류 검출, 재전송, 누적 확인응답, 타이머, 순서 번호와 확인응답 번호를 위한 헤더 필드를 포함해서 신뢰성있는 데이터 전송 원칙을 따른다.

TCP 연결

TCP 특징

  • 연결지향형(connection oriented)
    • 프로세스가 데이터를 다른 프로세스에게 보내기 전에 두 프로세스가 서로 핸드셰이크를 해야 한다.
  • 전이중 서비스(full-duplex service)
    • 호스트 A의 프로세스와 호스트 B의 프로세스가 서로 TCP로 연결되어 있다면 둘은 양방향으로 데이터를 전송할 수 있다.
  • 점대점(point-to-point)
    • 단일 송신자와 단일 수신자 사이의 점대점이다.
    • 한 송신자가 여러 수신자에게 데이터를 보내는 멀티캐스팅은 TCP에서 불가능하다.

TCP 세그먼트 크기 제한

  • TCP 세그먼트로 모아 담을수 있는 최대 데이터의 양은 최대 세그먼트 크기(maximum segment size, MSS)로 제한된다.
  • MSS는 일반적으로 로컬 송신 호스트에 의해 전송될 수 있는 가장 큰 링크 계층 프레임의 길이(최대 전송 단위(maximum transmission unit, MTU))에 의해 결정되고, 그 후에 TCP 세그먼트와 TCP/IP 헤더 길이(40바이트)가 단일 링크 계층 프레임에 딱 맞도록 하여 정해진다.
  • 이더넷과 PPP 링크 계층 프로토콜은 모두 1,500 바이트의 MTU를 갖는다. 따라서 일반적인 MSS의 값은 1460 바이트이다.

TCP는 TCP 헤더와 클라이언트 데이터를 하나로 짝지어 TCP 세그먼트(TCP segment)를 구성한다. 세그먼트는 네트워크 계층에 전달되며, 네트워크 계층 IP 데이터그램 안에 각각 캡슐화된다.

TCP 세그먼트 구조

  • sequence number, acknowledgement number
    • 신뢰적인 데이터 전송 서비스 구현에서 TCP 송신자와 수신자에 의해 사용된다.
  • receive window
    • 흐름 제어에 사용된다.
  • header field(4비트)
    • 32비트 워드 단위로 TCP 헤더의 길이를 나타낸다. TCP 헤더는 옵션 필드 때문에 가변적인 길이가 될 수 있다.
  • option
    • 송신자와 수신자가 최대 세그먼트 크기(MSS)를 협상하거나 고속 네트워크에서 사용하기 위한 윈도 확장 요소로 이용된다.
  • flag field
    • 6비트를 포함한다.
    • ACK : 확인응답 필드에 있는 값이 유용함을 가리키는데 사용된다. 즉, 이세그먼트는 성공적으로 수신된 세그먼트에 대한 확인 응답을 포함한다.
    • RST, SYN, FIN : 연결 설정과 해제에 사용된다.
    • PSH : 수신자가 데이터를 상위 계층에 즉시 전달해야 한다는것을 가리킨다.
    • URG : 이 세그먼트에서 송신측 상위 계층 개체가 '긴급'으로 표시되는 데이터임을 가리킨다.
  • urg data pointer field
    • URG가 표시된 TCP 세그먼트에서 긴급 데이터의 마지막 바이트의 위치는 이 필드에 의해 가리켜진다.

순서 번호와 확인응답 번호

세그먼트에 대한 순서 번호는 세그먼트에 있는 첫 번째 바이트의 바이트 스트림 번호다.

  • 데이터 스트림이 500,000인데 호스트 A가 호스트 B에 데이터를 보낼 때 MSS가 1,000바이트이라고 가정하면
    • 호스트 A는 각 세그먼트의 순서번호가 0, 1000, 2000, ... 4900이 될 것이다.

TCP는 호스트 A는 호스트 B로 데이터를 송신하는 동안에 호스트 B로부터 데이터를 수신하게 해주는 전이중 방식이다.

  • 호스트 A가 자신의 세그먼트에 삽입하는 확인응답 번호는 호스트 A가 호스트 B로부터 기대하는 다음 바이트의 순서 번호다.

몇 가지 예시

  • 호스트 A가 호스트 B로부터 0~535 바이트를 수신했다면, 확인 응답 번호 필드에 536을 설정하고 호스트 B에 송신한다.
  • 호스트 A가 0~535, 900~1000의 바이트를 수신했고, 536~899 바이트를 수신하지 않았다. 그럼 호스트 A는 호스트 B에 대한 확인 응답 번호로 536를 설정할 것이다.
    • TCP는 스트림에서 첫 번째 잃어버린 바이트까지의 바이트들 가지만 확인응답 하기 때문에, TCP는 누적 확인응답(cumulative acknowledgment)을 제공한다고 한다.
  • 호스트 A가 세 번째 세그먼트를 두 번째 세그먼트보다 먼저 수신했을때
    • 순서가 바뀐 세그먼트를 즉시 버린다.
    • 순서가 바뀐 데이터를 보유하고, 빈 공간에 잃어버린 데이터를 채우기 위해 기다린다.
      • 네트워크 대역폭 관점에서 효율적이며, 실제로 사용하는 방식이다.

신뢰적인 데이터 전송

인터넷 네트워크 계층(IP)는 비신뢰적이다.

  • 데이터그램 전달을 보장하지 않음
  • 데이터그램이 순서대로 전달된다는 것을 보장하지 않음
  • 데이터의 무결성을 보장하지 않음

TCP는 IP의 비신뢰적인 최선형 서비스에서 신뢰적인 데이터 전송 서비스(reliable data transfer service)를 제공한다.

  • 프로세스가 자신의 수신 버퍼로부터 읽은 데이터 스트림이 손상되지 않았으며 손실이나 중복이 없다는 것과 순서가 유지된다는 것을 보장한다.

몇 가지 흥미로운 시나리오

호스트 B가 A로부터 세그먼트를 전송 받았지만 확인 응답을 보내는 도중에 타임아웃이 발생

호스트 B는 호스트 A에서 재전송된 세그먼트의 바이트를 버릴 것이다.

호스트 A는 첫 번째 타임 아웃에서 아무런 응답을 받지 못해서 새로운 타이머때 Seq=92인 세그먼트를 재전송한다. 새로운 타임아웃 이전에 두 번째 세그먼트에 대한 ACK가 도착하므로, 두 번째 세그먼트는 재전송되지 않는다.

첫 번째 확인응답이 분실되었지만 두 번째 확인 응답이 전달되어 호스트 A는 호스트 B가 모든 응답을 받았음을 알게 되고 아무런 세그먼트도 재전송하지 않는다.

타임아웃 주기의 두 배로 설정

TCP는 타임아웃이 발생할 때 아직 확인 응답이 안 된 가장 작은 순서 번호를 가진 세그먼트를 재전송한다.

 

TCP는 타임아웃 주기를 이전 값의 두 배로 설정한다. 따라서 재전송의 주기는 재전송 후에 지수적으로 증가한다.

 

타이머 종료는 주로 네트워크의 혼잡에 의해 발생한다. 혼잡할 때 출발지에서 지속해서 패킷의 재전송을 고집하면 그 혼잡은 더욱 악화될 것이다. 대신에 TCP는 송신자가 더 긴 간격으로 재전송하도록 한다.

빠른 재전송

세그먼트를 잃었을 때, 긴 타임아웃 주기는 잃어버린 패킷을 다시 보내기 전에 송신자를 오랫동안 기다리게 해서 종단 간의 지연을 증가시킨다.

 

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

만약 TCP 송신자가 같은 데이터에 대해 3개의 중복 확인응답을 수신한다면, 이것은 ACK된 세그먼트의 다음 3개의 세그먼트가 분실되었음을 의미한다. 3개의 중복 ACK를 수신할 때, TCP는 세그먼트의 타이머가 만료되기 이전에 손실 세그먼트를 재전송하는 빠른 재전송(fast retransmit)을 한다.

흐름 제어

수신자가 데이터를 읽는 속도보다 송신자가 데이터를 더 빠르게 전송하면 수신자의 수신버퍼는 오버플로가 발생될 것이다.

 

TCP는 송신자가 수신자의 버퍼를 오버플로시키는 것을 방지하기 위해 애플리케이션에게 흐름 제어 서비스(flow-control-service)를 제공한다.

  • 수신하는 애플리케이션이 읽는 속도와 송신자가 전송하는 속도를 같게한다.
  • 송신자 제어의 이 형태는 혼잡 제어(congestion control)로 알려져 있다.

TCP는 송신자가 수신 윈도(receive window)라는 변수를 유지하여 흐름 제어를 제공한다. 수신 윈도는 수신 측에서 가용한 버퍼 공간이 얼마나 되는지를 송신자에게 알려주는데 사용한다.

수신자는 송신자에게 전송하는 모든 세그먼트의 윈도 필드에 현재의 rwnd값을 설정함으로써 연결 버퍼에 얼마만큼의 여유 공간이 있는지를 송신자에게 알려준다. 이는 오버플로 발생을 방지해준다.

 

흐름제어의 문제점과 해결방법

  • 수신버퍼의 rwnd=0이고, 수신자는 송신자에게 전송할게 없는 경우
  • 수신자가 버퍼를 비우더라도 송신자에게 새로운 rwnd로 새로운 세그먼트를 전송하지 않는다.
  • 송신자는 수신자의 버퍼에 여유가 있는지 알지 못하고 데이터를 전송할 수 없다.
  • TCP 명세서는 송신자가 수신자의 수신 윈도가 0일때, 1바이트 데이터로 세그먼트를 계속해서 전송하도록 요구한다.
    • 이 세그먼트들은 수신자에 의해 긍정 확인응답될 것이다.
    • 결과적으로 버퍼는 비워지고 긍정 확인응답은 0이아닌 rwnd값을 포함한다.

TCP 연결 관리

세 방향 핸드셰이크(three-way handshake) 과정

  • 클라이언트측에서 서버측에 특별한 TCP 세그먼트를 송신한다.
    • 세그먼트는 애플리케이션 계층 데이터를 포함하지 않는다.
    • SYN 비트를 1로 설정한다.
    • 최초의 순서 번호(client_isn, seq 번호)를 임의로 선택하고 TCP SYN 세그먼트의 순서 번호 필드에 넣는다.
  • 서버는 TCP 세그먼트를 추출하고, 연결에 TCP 버퍼와 변수를 할당한다. 그리고 클라이언트 TCP로 연결 승인 세그먼트를 송신한다.
    • 세그먼트는 애플리케이션 계층 데이터를 포함하지 않는다.
    • SYN 비트를 1로 설정한다.
    • TCP 세그먼트 헤더의 확인 응답 필드(ack)는 client_isn + 1로 설정한다.
    • 서버는 자신의 최초의 순서 번호(server_isn, seq 번호)를 선택하고, TCP 세그먼트 헤더의 순서 번호 필드 값에 이 값을 넣는다.
  • 연결 승인 세그먼트를 수신하면, 클라이언트는 연결에 버퍼와 변수를 할당한다. 그 다음에 클라이언트 호스트는 서버로 또 다른 세그먼트를 송신한다.
    • server_isn + 1값을 통해 서버의 연결 승인 세그먼트를 확인한다.
    • 연결이 설정되었기 때문에 SYN 비트는 0으로 설정된다.
    • 이 때 클라이언트에서 서버로의 데이터를 세그먼트 페이로드에서 운반할 수 있다.

TCP에서 연결을 끝내는 과정

  1. 클라이언트가 FIN 비트를 1로 설정한 값을 세그먼트 헤더에 포함한 후 서버에 송신한다.
  2. 서버가 세그먼트를 수신하면 확인응답(ACK) 세그먼트를 송신한다.
  3. 서버는 그다음에 FIN 비트를 1로 설정한 자신의 종료 세그먼트를 송신한다.
  4. 클라이언트는 서버의 종료 세그먼트에 확인 응답을 한다.

'네트워크' 카테고리의 다른 글

네트워크 계층 개요  (0) 2024.02.23
혼잡 제어  (1) 2024.02.19
신뢰적인 데이터 전송의 원리  (0) 2024.02.01
UDP  (0) 2024.01.29
트랜스포트 계층 개요, 다중화와 역다중화  (0) 2024.01.26