TCP와 UDP의 목적과 특징
포트를 통한 프로세스 식별
패킷의 최종 송수신 대상은 프로세스이므로 포트 번호를 통해 프로세스를 식별
네트워크 패킷을 주고받는 프로세스는 포트 번호가 할당되어 {IP : 포트 번호}로 함께 표기됨
포트를 통한 프로세스 식별이 전송 계층(TCP, UDP)의 주된 목적이므로 헤더에 송신지 포트 번호와 수신지 포트 번호를 포함
포트 번호는 16비트로 총 2^16(65536)개로, 잘 알려진 포트(0~1023), 등록된 포트(1024~49151), 동적 포트(49152~65535)로 나뉨
서버로서 동작하는 프로그램은 잘 알려진 포트와 등록된 포트가 할당되는 경우가 많고, 클라이언트로서 동작하는 프로그램은 동적 포트로 할당되는 경우가 많음
NAT(Network Address Translation)
공인 IP와 사설 IP 간 변환에 사용되는 기술
패킷이 사설 네트워크에서 네트워크 외부로 전송될 때 사설 IP -> 공인 IP 변환
패킷이 네트워크 외부에서 사설 네트워크로 전송될 때 공인 IP -> 사설 IP 변환
NAPT(Network Address Port Translation)
사설 IP와 공인 IP를 일대일로 대응하지 않고 다수의 사설 IP가 적은 수의 공인 IP로 변환될 때 포트를 사용
서로 다른 사설 IP가 같은 공인 IP로 변환돼도 포트 번호에 따라 사설 IP를 구분
공인 IP의 부족 문제를 개선
(비)신뢰성과 (비)연결형 보장
TCP : 신뢰, 연결형
UDP : 비신뢰, 비연결형
TCP는 패킷을 주고받기 전에 연결 수립 과정을 거치며 패킷의 신뢰성을 보장하기 위해 상태 관리, 흐름 제어, 오류 제어, 혼잡 제어 등의 각종 기능을 제공, 패킷의 송수신이 모두 끝나면 연결 종료
UDP는 연결의 수립이나 종료 단계를 거치지 않고, 신뢰성을 높이기 위한 기능도 제공하지 않아 헤더가 비교적 작음
신뢰할 수 있는 연결형 송수신에는 시간과 연산이 필요하기 때문에 일반적으로 TCP가 UDP에 비해 송수신 속도가 느림
따라서 패킷의 유실 없는 송수신을 원하면 TCP를 선택하고, 비교적 빠른 송수신(실시간 스트리밍, 온라인 게임, 인터넷 전화 등)을 원한다면 UDP를 선택하는 것이 유리
UDP 헤더에는 송신지 포트, 수신지 포트, 길이(UDP 데이터그램의 바이트 크기), 체크섬(checksum, 송수신 과정에서 데이터그램 훼손 여부)가 명시됨
TCP는 연결의 수립과 종료, 신뢰성 보장을 위한 다양한 기능을 제공하여 헤더 필드 수가 많음, 그 중 순서 번호, 확인 응답 번호, 제어 비트가 중요
애플리케이션 레벨에서 커스텀 프로토콜을 정의하여 UDP의 신뢰성 문제를 보완할 수 있음
- 클라이언트가 데이터를 보내면, 서버는 수신 확인 메시지(ACK)를 전송
- 클라이언트가 일정 시간 내에 ACK를 받지 못하면 데이터를 다시 전송, 이 과정에서 연결이 유효한지 확인
- 각 패킷에 시퀀스 번호를 부여해 데이터의 순서를 보장하거나, 중복된 패킷을 식별할 수 있음
순서 번호
TCP 세그먼트의 올바른 송수신 순서를 보장하기 위해 세그먼트 첫 바이트에 매겨진 번호
순서 번호를 통해 현재 주고받는 TCP 세그먼트가 송수신하고자 하는 데이터의 몇 번째 바이트에 해당하는지 알 수 있음
확인 응답(acknowledgement) 번호
상대 호스트가 보낸 세그먼트에 대한 응답으로, 다음으로 수신하길 기대하는 순서 번호
일반적으로 올바르게 수신한 순서 번호에 1을 더한 값으로 설정됨
호스트 A가 순서 번호 100인 세그먼트를 전송했고 호스트 B가 받아서 다음으로 101번 세그먼트를 받기 위해 확인 응답 번호에 101을 명시
각각 순서 번호와 확인 응답 번호가 함께 사용되므로 한 쌍 처럼 기억
제어 비트(control bit, 플래그 비트)
세그먼트에 대한 부가 정보
기본적으로 8비트로 구성
ACK
세그먼트의 확인 응답 번호가 포함됐는지 여부
제어 비트에서 승인을 나타내는 비트로, 확인 응답 번호를 보내기 위해서는 ACK 플래그가 1로 설정돼야 함
SYN
연결을 수립하기 위한 비트
FIN
연결을 종료하기 위한 비트
TCP의 연결부터 종료까지
TCP의 연결 수립(3-way handshake)
1. [A->B] SYN 세그먼트 전송
호스트 A가 SYN 비트가 1인 세그먼트를 호스트 B에게 전송
세그먼트의 순서 번호에는 호스트 A의 순서 번호가 포함됨
2. [B->A] SYN + ACK 세그먼트 전송
호스트 B는 SYN, ACK 비트가 1인 세그먼트를 호스트 A에게 전송
1번에 대한 호스트 B의 응답
세그먼트의 순서 번호에는 호스트 B의 순서 번호와 1번에서 보낸 세그먼트에 대한 확인 응답 번호가 포함됨
3. [A->B] ACK 세그먼트 전송
호스트 A는 ACK 비트가 1인 세그먼트를 호스트 B에게 전송
세그먼트의 순서 번호에는 호스트 A의 순서 번호와 2번에서 보낸 세그먼트에 대한 확인 응답 번호가 포함됨
TCP 연결 수립 과정에서 SYN 비트가 설정된 패킷을 처음으로 보내는 호스트가 처음으로 연결 요청을 보내는 호스트
액티브 오픈
호스트 A처럼 처음 연결을 시작하는 과정
패시브 오픈
호스트 B처럼 연결 요청을 수신한 뒤 그에 대한 연결을 수립하는 과정
서버-클라이언트 관계에서 액티브 오픈은 주로 클라이언트에 의해 수행되고 패시브 오픈은 주로 서버에 의해 수행됨
TCP의 오류, 흐름, 혼잡 제어
재전송을 통한 오류 제어
TCP는 송수신 과정에서 잘못 전송된 세그먼트가 있을 경우 재전송하여 오류를 제어
잘못 전송된 경우는 중복된 ACK 세그먼트가 도착했을 경우와 타임아웃이 발생했을 경우
TCP의 송수신은 기본적으로 순서 번호(n) 세그먼트를 보내고 확인 응답이 담긴 세그먼트를 받고 다음 순서 번호(n+1) 세그먼트를 보내는 과정이 반복하며 이루어짐
중복된 ACK 세그먼트를 수신하는 상황
송신한 세그먼트가 유실되어 다음 순서 번호(n+1)이 아닌 n을 보내는 상황
타임아웃이 발생한 상황
TCP 세그먼트를 송신하는 호스트는 세그먼트를 전송할 때마다 재전송 타이머를 시작하여 타이머의 카운트다운이 끝났을 때까지 ACK 세그먼트를 받지 못한 상황
파이프라이닝 전송
순차적으로 세그먼트를 송수신하는 것은 비효율이므로 오늘날 TCP가 송수신하는 방식
한 번에 세그먼트를 송신하고 한 번에 세그먼트에 대한 확인 응답을 받는 방식
흐름 제어
수신 호스트가 한 번에 처리할 수 있는 만큼만 전송하여 송수신 속도를 균일하게 맞추는 기능
수신 호스트가 한 번에 받을 수 있는 전송량은 TCP 수신 버퍼의 크기에 결정됨
수신 버퍼는 수신된 세그먼트가 애플리케이션 프로세스에 의해 읽히기 전에 임시 저장되는 공간으로 커널에 정의됨
수신 호스트가 TCP 헤더의 윈도우 필드를 통해 송신 호스트에게 수신 버퍼의 크기를 알려주고 송신 호스트는 전달받은 값을 토대로 세그먼트를 전송
혼잡 제어
많은 트래픽으로 패킷의 처리 속도가 느려지거나 유실될 수 있는 상황을 제어하는 기능
혼잡 제어의 주체는 송신 호스트
송신 호스트는 중복된 ACK 세그먼트가 도착했을 때, 타임아웃이 발생했을 때 혼잡할 수 있다고 판단하고 혼잡 윈도우(congestion window, 혼잡 없이 전송할 수 있는 정도의 양)의 값을 넘지 않게 송신
혼잡 윈도우 크기는 혼잡 제어 알고리즘(혼잡 윈도우 크기를 연산하는 방법)을 통해 계산
AIMD(Additive Increase/Multiplicative Decrease)
가장 기본적인 혼잡 제어 알고리즘
세그먼트를 송수신할 때 혼잡이 감지되지 않으면 혼잡 윈도우를 1씩 증가하고, 혼잡이 감지되면 절반으로 떨어뜨림
RTT(Round Trip Time)
패킷을 보내고 응답이 수신되기까지의 시간
흐름 제어에 사용되는 윈도우와 혼잡 제어에 사용되는 혼잡 윈도우는 모두 커널에 정의된 값
TCP의 종료(4-way-handshake)
1. [A->B] FIN 세그먼트 전송
호스트 A는 FIN 비트가 1로 설정된 세그먼트를 호스트 B에게 전송
2. [B->A] ACK 세그먼트 전송
1번에 대한 호스트 B의 응답
호스트 B는 ACK 세그먼트를 호스트 A에게 전송
3. [B->A] FIN 세그먼트 전송
호스트 B는 FIN 세그먼트를 호스트 A에게 전송
4. [A->B] ACK 세그먼트
3번에 대한 호스트 A의 응답
호스트 A는 ACK 세그먼트를 호스트 B에게 전송
액티브 클로즈(close)
먼저 연결을 종료하려는 호스트에 의해 수행되는 동작
패시브 클로즈
연결 종료 요청을 받아들이는 호스트에 의해 수행되는 동작
TCP의 상태 관리
TCP는 상태를 유지하고 관리하는 프로토콜로 Stateful 프로토콜로 부름
상태
현재 어떤 통신 과정에 있는지를 나타내는 정보
TCP의 상태 정보를 토대로 현재 TCP 송수신 현황을 판단할 수 있고, 디버깅의 힌트로도 활용할 수 있음
TCP 상태 플로우
연결이 수립되지 않았을 때
CLOSED : 연결이 없는 상태
LISTEN : 연결 대기 상태(3-way handshake에서 1번 SYN 세그먼트를 대기하는 상태)
연결 수립 과정
SYN-SENT : 액티브 오픈 호스트가 SYN 세그먼트를 보낸 뒤, 그에 대한 응답인 SYN + ACK 세그먼트를 기다리는 상태(연결 요청 전송)
SYN-RECEIVED : 패시브 오픈 호스트가 SYN + ACK 세그먼트를 보낸 뒤, 그에 대한 ACK 세그먼트를 기다리는 상태(연결 요청 수신)
ESTABLISHED : 3-way-handshake가 끝난 뒤 데이터를 송수신할 수 있는 상태(연결 수립)
연결 종료 과정
FIN-WAIT-1 : 액티브 클로즈 호스트가 FIN 세그먼트로 연결 종료 요청을 보낸 상태
CLOSE-WAIT : FIN 세그먼트를 받은 패시브 클로즈 호스트가 그에 대한 응답으로 ACK 세그먼트를 보낸 후 대기하는 상태(연결 종료 요청 승인)
FIN-WAIT-2 : FIN-WAIT-1 상태에서 ACK 세그먼트를 받은 상태
LAST-ACK : CLOSE-WAIT 상태에서 FIN 세그먼트를 전송한 뒤 대기하는 상태
TIME-WAIT : 액티브 클로즈 호스트가 마지막 ACK 세그먼트를 전송한 상태
패시브 클로즈 호스트가 마지막 ACK 세그먼트를 수신하면 CLOSE 상태가 되는 반면, TIME-WAIT 상태에 접어든 액티브 클로즈 호스트는 일정 시간을 기다린 뒤 CLOSED 상태가 됨
이는 마지막 ACK 세그먼트가 올바르게 전송되지 않았을 때 재전송하기 위함
CLOSING : 서로가 FIN 세그먼트를 보내고 받은 뒤 각자 그에 대한 ACK 세그먼트를 보냈지만 아직 자신의 FIN 세그먼트에 대한 ACK 세그먼트를 받지 못한 상태