TCP 연결
TCP의 특징
TCP는 애플리케이션 프로세스가 데이터를 다른 프로세스에게 보내기 전에,
두 프로세스가 서로 "핸드셰이크"를 먼저 해서 연결을 시키는 사전 작업이 필요하다.
따라서 TCP는 연결을 성공시킨 뒤 데이터를 확실하게 주고 받는 연결 지향형이다.
즉, 데이터 전송을 보장하는 파라미터들을 각자 설정하기 위한 사전 세그먼트들을 보내야 한다.
파라미터로는 송수신 포트번호 등이 있다.
TCP 프로토콜은 오직 종단 시스템에서만 동작하고 중간의 네트워크 계층의 요소들(라우터, 스위치) 에서는 동작하지 않는다.
따라서 중간의 네트워크 계층의 요소들은 TCP 연결상태를 유지하지 않고, 현재 전송되는 데이터가 TCP 방식인지도 알 수 없다.
TCP 연결은 전이중(full-duplex)서비스를 제공한다.
전이중이란?
만약 A호스트와 B호스트의 프로세스 사이에 TCP 연결이 되어 있다면, 애플리케이션 계층 데이터는 B에서 A로 흐르는 동시에 A에서 B로도 흐를 수 있다는 뜻이다.
또한 TCP연결은 항상 단일 송신자와 단일 수신자 사이의 점대점(point-to-point)방식이다.
TCP 연결 설정
이제 TCP 연결이 어떻게 설정되는지 알아보자.
연결을 초기화 시켜주는 프로세스를 클라이언트 프로세스, 다른 프로세스를 서버 프로세스라고 부른다.
- 클라이언트가 먼저 특별한 TCP 세그먼트를 보낸다.
- 그리고 서버는 또 다른 특별한 TCP 세그먼트로 응답을 보낸다.
- 마지막으로 클라이언트는 애플리케이션 데이터를 포함한 세그먼트를 서버로 보낸다.
처음 2개의 세그먼트에는 애플리케이션 계층 데이터가 없다.
하지만 세 번째 세그먼트에는 데이터가 포함 될 수 있다. 이때 애플리케이션 계층 데이터를 "페이로드"라고 부른다.
위와 같은 연결 설정 절차를 '3-way 핸드셰이크' 라고 한다.
일단 TCP 연결이 설정되면 두 애플리케이션 프로세스는 서로 데이터를 주고 받을 수 있게 된다.
- 클라이언트 프로세스는 소켓을 통해서 데이터를 트랜스포트 계층으로 전달한다.
- 데이터는 TCP 전송 버퍼로 보내지게 되고, TCP는 주로 데이터의 묶음을 만들어서 전송 네트워크로 보낸다.
TCP 명세서를 보면 자신이 편한 대로 세그먼트 데이터를 전송하라고 기술되어 있고, 버퍼된 데이터를 언제 전송하는지는 기술되어 있지 않다. -> 개발자의 재량
세그먼트의 크기는 최대 세그먼트 크기(Maximum Segment Size, MSS)로 제한된다.
MSS는 일반적으로 로컬 송신 호스트에 의해 전송될 수 있는 가장 큰 링크 계층 프레임의 길이(최대 전송 단위(Maximum Transmission Unit, MTU))에 의해 일단 결정되고, 이후에 TCP 세그먼트와 TCP/IP헤더의 길이가 단일 링크 계층 프레임에 딱 맞도록 정해진다.
MTU가 너무 크면 커다란 크기의 패킷을 처리할 수 없는 라우터를 만났을 때 재전송 해야하는 경우가 생길 수 있다. 이와는 반대로 MTU가 너무 작으면, 상대적으로 헤더 및 송수신 확인에 따르는 오버헤드가 커지게 된다.
TCP는 네트워크 인터페이스(링크 계층)의 MTU 크기를 사용한 다음 프로토콜 헤더를 빼는 방식으로 MSS를 계산하여 TCP 세그먼트의 데이터 크기를 구한다. 예를 들어, MTU가 1500인 이더넷일때 IPv4 헤더를 포함한 경우 20바이트를 빼고 TCP 헤더도 포함한 경우 20바이트를 빼서 MSS는 1460이 된다.
TCP는 TCP헤더와 클라이언트 데이터를 하나로 만들어 TCP 세그먼트를 형성한다. 세그먼트는 네트워크 계층에 전달되며, 네트워크 계층 IP 데이터그램 안에 각각 캡슐화 된다. TCP가 상대에게서 세그먼트를 수신했을 때, 위 그림 처럼 세그먼트의 데이터는 TCP 연결의 수신 버퍼에 위치한다.
TCP 세그먼트 구조
TCP 연결을 살펴보았으므로 TCP 세그먼트 구조를 알아보자.
TCP 세그먼트는 헤더 필드와 데이터 필드로 구성되어 있다. 데이터 필드는 MSS에 의해 크기가 제한된 작은 애플리케이션 데이터를 담는다. TCP가 웹 문서의 이미지와 같은 큰 파일을 전송할 때, 일반적으로 MSS 크기로 파일을 쪼갠다. 그러나 많은 대화식 애플리케이션은 MSS보다 작은 데이터 덩어리를 전송한다. TCP 헤더는 일반적으로 20바이트 이므로 데이터 덩어리가 1바이트라면 1바이트 전송을 하기 위해 헤더 20바이트도 같이 전송을 해야하므로 데이터 전송을 위한 오버헤드가 클 것이다.
아래 그림은 TCP 세그먼트의 구조를 보여준다.
다중화와 역다중화를 하는데 필요한 출발지 포트 번호와 목적지 포트 번호를 가진다.
32비트 순서번호 필드와 32비트 확인응답번호 필드를 가진다. - 송신자와 수신자 간의 신뢰적인 데이터 전송을 위해 사용된다.
16비트 수신 윈도우필드는 흐름제어에 사용된다. 이는 수신자가 받아들이려는 바이트의 크기를 나타내는 데 사용된다.
4비트 헤더 길이 필드는 32 비트 워드 단위로 TCP 헤더의 길이를 나타낸다. TCP 헤더의 길이는 그림에서 볼 수 있는 옵션 필드 때문에 가변적이다. (일반적으로 옵션 필드는 TCP의 길이가 20바이트가 되도록 비어있다.)
옵션필드는 송신자와 수신자가 MSS를 협상하거나 고속 네트워크에서 사용하기 위한 윈도우 확장 요소로 이용된다. + 타임 스탬프 옵션까지.
플래그 필드는 아래의 6비트를 포함한다.
URG (Urgent) - Urgent Pointer 필드에 값이 채워져있음을 알린다.
송신측 상위 계층이 긴급 데이터라고 알려주면, 긴급비트 URG를 1 로 설정하고, 순서에 상관없이 먼저 송신됨
-> 긴급 데이터의 마지막 바이트 위치가 Urgent Pointer로 가리켜짐.
ACK (Acknowledgement) - 확인응답 필드에 확인응답번호(Acknowledgement Number) 값이 셋팅됨을 알림 .
1로 셋팅되면, 확인번호 유효함을 뜻함.
0으로 셋팅되면, 확인번호 미포함 (즉, 32 비트 크기의 확인응답번호 필드 무시됨)
-> TCP 연결 시작 후 모든 세그먼트에는 항상 이 비트가 1로 셋팅됨
PSH (Push) - 버퍼링된 데이터를 가능한 빨리 상위 계층 응용프로그램에 즉시 전달. 수신측은 버퍼가 찰 때까지 기다리지 않고, 수신 즉시 버퍼링된 데이터를 응용프로그램에 전달).
Telnet 세션에서 `q` 입력 만으로 세션 종료를 알릴 때 등에 사용.
서버측에서 더이상 전송할 데이터가 없음을 나타내기도 한다.
* 아래 3개 비트 플래그(RST,SYN,FIN)는 TCP 연결설정 및 TCP 연결종료에 주도적으로 사용된다.
RST (Reset) [강제 연결 초기화 용도] - 연결확립된 회선에 강제 리셋 요청.
강제 리셋 : RST=1. 연결 상의 문제를 발견한 장비가 RST 플래그를 '1'로 설정한 TCP 세그먼트를 전송 한다.
* 연결 문제 등의 상황 처리를 위한 특별한 초기화용 제어 비트
SYN (Synchronize) [연결시작,회선개설 용도] - TCP 연결설정 초기화를 위한 순서번호의 동기화
TCP 연결 설정. 연결요청 : SYN=1, ACK=0 (SYN 세그먼트).
연결허락 : SYN=1, ACK=1 (SYN+ACK 세그먼트)
연결설정 : ACK=1 (ACK 세그먼트)
* 송수신 간에 순서번호의 동기화
FIN (Finish) [연결해제,회선종결 용도] - 송신기가 데이타 보내기를 끝마침
TCP 연결 종료.
종결요청 : FIN=1 (FIN 세그먼트).
종결응답 : FIN=1, ACK=1 (FIN+ACK 세그먼트)
* 즉, 연결을 종료하고 싶다는 뜻을 상대에게 보내는 것
TCP세그먼트 헤더에서 가장 중요한 필드 두 가지는 순서번호 필드(SYN)와 확인응답 번호 필드(ACK)이다.
이 필드들이 어떻게 채워지는지 알아보자.
TCP는 데이터를 순서대로 정렬된 바이트 스트림으로 본다. TCP의 순서번호 사용은 이를 반영해서 일련의 전송된 바이트 스트림에 대한 것이다.
세그먼트에 대한 순서번호는 세그먼트에 있는 첫 번째 바이트의 바이트-스트림 번호이다.
호스트 A의 프로세스는 TCP 연결 상에서 호스트 B의 프로세스로 500,000바이트의 데이터 스트림의 전송을 원한다고 가정해보자.
MSS는 1000 바이트이고 데이터 스트림의 첫 번째 바이트는 0 으로 설정 된다.
따라서 첫 번째 세그먼트의 순서번호는 0, 두번째 세그먼트의 순서번호는 1000, 세 번째는 2000 과 같은 식으로 할당된다.
이제 확인응답 번호를 생각해보자. TCP는 전이중 방식이므로 A가 B로 데이터를 전송하는 동안에 A는 B의 데이터를 받을 수 있다. 아래 3가지의 예시가 나오는데 전이중 방식을 기억하자. 호스트 B에서 온 세그먼트는 특정한 TCP연결을 통해 B로부터 A로 들어온 데이터에 대한 순서번호를 갖는다. 호스트 A가 자신의 세그먼트에 삽입하는 확인응답번호는 호스트 A가 호스트 B로부터 받기를 기대하는 다음 바이트의 순서번호이다.
예를 들어서 알아보자.
호스트 A가 B로부터 0~535 번호가 붙은 모든 바이트를 수신했다고 가정하자. 그리고 호스트 B로 데이터를 송신하려고 한다고 가정하자. 호스트 A는 호스트 B의 데이터 스트림에서 536번째 바이트와 그다음에 오는 모든 바이트를 기다리고 있다. 그래서 호스트 A는 세그먼트의 확인응답 번호 필드에 536을 삽입하고 그것을 B에 송신한다.
두 번째 예로 호스트 A가 호스트 B로부터 0~535 바이트를 포함하는 어떤 세그먼트와 900~1000을 포함하는 세그먼트를 수신했다고 하자. 호스트 A는 아직 536~899 번 바이트를 수신하지 않았다. 그러므로 B에 대한 A의 다음 세그먼트는 확인응답 번호 필드에 536을 가질 것이다. TCP는 스트림에서 첫 번째 잃어버린 바이트만 확인응답하기 때문에 TCP는 누적 확인응답을 제공한다고 한다.
세 번째 예로 호스트 A는 900~1000 세그먼트를 536~899 세그먼트가 수신되기 전에 받았다고 가정하자. 순서가 틀리게 도착했지만 TCP 명세에는 어떤 규칙도 부여하고 있지 않다. TCP 구현 개발자에게 이를 맡기고 있는 셈이다.
1) 수신자는 순서가 틀린 세그먼트를 즉시 버린다. 2) 수신자는 순서가 틀린 데이터를 보유하고, 빈 공간에 잃어버린 데이터를 채우기 위해서 기다린다.
위 예시들에서 데이터 스트림의 시작번호는 0으로 설정했다. 하지만 두 호스트는 시작 순서 번호를 임의로 설정해야한다. 왜냐하면 두 호스트 사이에서 이미 종료된 연결로부터 남아있는 데이터가 동일한 포트를 사용하는 나중 연결에서 유효한 세그먼트로 오인될 확률 최소화 해주기 때문이다.
왕복시간 예측과 타임아웃
TCP는 확인응답과 타이머를 사용함으로써 신뢰적인 데이터 전송을 제공한다. TCP는 정확하게 수신한 데이터에 대한 확인응답을 하며, 세그먼트 또는 이에 해당하는 확인응답이 손실, 손상되었다고 생각될 때, 세그먼트를 재전송 하도록 한다. 그리고 신뢰적인 데이터 전송을 위해 타임아웃기능은 필수적이다. 세그먼트가 IP에 넘겨진 시간부터 해당 세그먼트에 대한 확인응답이 도착한 시간까지의 시간을 SampleRTT라고 한다. 애플리케이션 데이터가 여러 세그먼트로 다중화 되고 각 세그먼트에 대한 SampleRTT가 존재한다. 이러한 SampleRTT들은 라우터에서의 혼잡과 호스트에서의 부하 변화 때문에 모두 다르게 된다. 따라서 SampleRTT에 임의의 가중치를 두어서 나중의 세그먼트 왕복시간에 대한 예측을 할 수 있게 된다.
TCP의 신뢰성을 보여주는 몇 가지 시나리오
ack=100인 세그먼트가 중간에 소실되었지만, 타임아웃 시간동안 응답이 오지 않자 자동으로 전에 보냈던 세그먼트를 재전송하는 모습이다
타임아웃 시간이 지나서 seq=92인 세그먼트를 재전송 했다.
새로운 seq=92 세그먼트의 재전송 타임아웃 중간에, 오래된 seq=92 세그먼트에 대한 응답이 도착했다.
새로운 seq=92에 대한 응답은 이제 필요가 없어진 셈이므로 새로운 seq=92의 타임아웃이 지나도 세그먼트를 재전송하지 않는다.
중복 ACK
송신자가 이미 이전에 받은 확인 응답에 대한 재확인응답 세그먼트 ACK이다.
TCP 수신자가 기다리는 다음 것보다 더 큰 순서번호를 가진 세그먼트를 받았을 때, TCP수신자는 그 데이터 스트림에서의 간격을 찾아낼 수 있다. 이 간격은 네트워크 안에서의 세그먼트를 잃어버리거나 순서가 바뀐 결과일 수 있다.
송신자는 종종 많은 양의 세그먼트를 연속적으로 보낼 수 있으므로, 만약 하나의 세그먼트를 잃어버린다면, 많은 연속적인 중복 ACK들이 존재할 수 있다. 만약 TCP송신자가 같은 데이터에 대해 3개의 중복 확인응답을 수신한다면, 이것은 ACK 세그먼트의 다음 3개의 세그먼트들이 위치가 잘못되었음을 알 수 있다. 이렇게 중복 ACK를 수신하는 경우 TCP는 세그먼트의 타이머가 만료되기 이전에 손실 세그먼트를 재전송하는 빠른 재전송을 한다.
'CS > Network' 카테고리의 다른 글
[Network] 네트워크 계층 : 개요와 서비스 모델 (0) | 2021.10.01 |
---|---|
[Network] 트랜스포트 계층 : 흐름제어, TCP 연결 (0) | 2021.09.28 |
[Network] 트랜스포트 계층 : 다중화와 역다중화 (0) | 2021.09.17 |
[Network] 트랜스포트 계층 : 개요(Intro) (0) | 2021.09.16 |
[Network] 인터넷 프로토콜 계층과 캡슐화 (0) | 2021.09.09 |