본문 바로가기

혼자 공부하는 네트워크

[혼공네트] Ch4. 전송 계층

4-1 전송 계층 개요: IP의 한계와 포트

네트워크 게층의 IP는 신뢰할 수 없는 통신비연결형 통신을 수행한다는 한계가 있다.

네트워크 계층과 응용 계층 사이에 위치한 전송 계층은 신뢰할 수 있는 통신과 연결형 통신을 가능하게 하고, 포트 번호를 통해 응용 계층의 애플리케이션 프로세스들을 식별하는 역할을 한다. 

 

신뢰할 수 없는 통신과 비연결형 통신

네트워크 계층의 핵심 프로토콜인 IP는 비신뢰성 프로토콜이자 비연결형 프로토콜이라는 특징을 가지고 있다. 

신뢰할 수 없는 통신은 IP 프로토콜이 패킷이 수신지까지 제대로 전송되었다는 보장을 하지 않는 특징을 말한다. 이는 통신 과정에서 패킷의 데이터가 손상되거나 중복된 패킷이 전송되었더라도 이를 확인하지 않고, 재전송하지도 않으며, 순서대로 패킷이 도착할 것이라는 보장도 하지 않는다는 의미이다. 이는 다른 말로 최선형 전달이라 부르며, '최선을 다해보지만, 전송 결과 대해서는 어떠한 보장도 하지 않겠다'는 의미이다. 

비연결통신은 송수신 호스트 간에 사전 연결 수립 작업을 거치지 않는 특징을 의미한다. 

 

이러한 특징을 가진 이유는 성능 때문이다. 모든 패킷이 전송되었는지 일일히 확인하고, 호스트 간에 연결을 수립하는 작업은 일반적으로 더 많은 시간, 대역폭, 부하가 요구되며, 이는 곧 성능 상의 악영향으로 이어질 수 있다.

인터넷 상에서 돌아다니는 패킷은 종류는 다양하다. 따라서 금융 서비스처럼 반드시 신뢰성 있는 전송을 보장해야하는 경우도 있지만, 동영상 스트리밍과 같은 서비스의 경우 한 두개의 패킷 손실을 감수하더라도 빠른 전송이 우선시되는 경우가 있다. 이처럼 신뢰성 있는 전송이 모든 경우에 필요한 것은 아니다. 

 

IP의 한계를 보완하는 전송 계층

1. 전송 계층은 연결형 통신을 가능하게 한다.

연결형 통신을 지원하는 대표적인 전송 프로토콜로 TCP가 있다. TCP는 회선 교환 네트워크와 유사하게 두 호스트가 정보를 주고받기 전에 가상의 회선을 설정하듯이 연결을 수립한다. 송수신하는 동안에는 연결을 유지하고, 송수신이 끝나면 연결을 종료할 수 있다.

2. 전송 계층은 신뢰성 있는 통신을 가능하게 한다.

TCP는 패킷이 수신지까지 올바른 순서대로 확실히 전달되는 것을 보장하기 위해 재전송을 통한 오류 제어, 흐름 제어, 혼잡 제어 등 다양한 기능들을 제공한다. 

 

때로는 비교적 높은 성능을 위해 신뢰할 수 없는 통신, 비연결형 통신을 지원하는 프로토콜이 필요할 때가 있다. 이때 UDP라는 프로토콜을 사용할 수 있다. UDP는 신뢰할 수 없는 통신, 비연결형 통신을 가능하게 하는 전송 계층의 프로토콜로 TCP보다는 비교적 빠른 전송이 가능하다. 

 

응용 계층과의 연결 다리, 포트

응용 계층과의 연결 다리 역할로서의 전송 계층을 살펴보자.

 

포트의 정의

패킷은 컴퓨터에 도달한 것 뿐만아니라 웹브라우저, 게임, 메신저 프로그램에 전달되어야 한다. 즉, 패킷은 실행 중인 특정 애플리케이션 프로세스까지 전달되어야한다. 결국 패킷의 최종 수신 대상은 특정 애플리케이션 프로세스다.

만약 패킷을 수신할 애플리케이션에 대한 정보가 패킷에 포함되어있지 않다면 해당 패킷을 어떤 애플리케이션에 전달해야 할지 알 수 없다. 즉, 패킷이 실행 중인 특정 애플리케이션까지 전달되려면 패킷에 특정 애플리케이션을 식별할 수 있는 정보가 포함되어 있어야 한다. 이러한 정보를 포트라고 한다.

💡프로세스란
프로세스는 실행 중인 프로그램을 의미한다. 각 프로세스는 PID라는 번호로 식별된다.

 

포트의 분류

전송 계층에서는 포트 번호를 통해 특정 애플리케이션을 식별한다. 패킷 내 수신지 포트와 송신지 포트를 통해 송수신지 호스트의 애플리케이션을 식별한다. 

전송 계층의 핵심 프로토콜인 TCP와 UDP는 모두 송신지 포트 번호화 수신지 포트 번호를 포함한다. 포트 번호는 16비트로 표현 가능하며 사용 가능한 포트의 수는 2¹⁶(65536)개이다. 할당 가능한 포트 번호는 0번부터 65535번까지 총 65536개가 존재한다. 포트 번호는 번호의 범위에 따라 세 종류로 나뉜다. '잘 알려진 포트', '등록된 포트', '동적 포트'이다.

 

0번부터 1023번까지는 잘 알려진 포트이다. 시스템 포트라 부르기도 한다. 잘 알려진 포트는 범용적으로 사용되는 애플리케이션 프로토콜이  일반적으로 사용하는 포트 번호를 의미한다.

  • 20, 21번 → FTP
  • 22번 → SSH
  • 23번 → TELNET
  • 53번 → DNS
  • 67, 68번 → DHCP
  • 80번 → HTTP
  • 443번 → HTTPS

1024번 부터 49151번까지는 등록된 포트 번호이다. 잘 알려진 포트에 비해서는 덜 범용적이지만, 흔히 사용되는 애플리케이션 프로토콜에 할당하기 위해 사용된다. 

  • 1194  OpenVPN
  • 1433  Microsoft SQL Server 데이터베이스
  • 3306  MySQL 데이터베이스
  • 6379  redis
  • 8080  HTTP 대체

49152번부터 65535번까지는 동적 포트, 사설 포트, 임시 포트라고 부른다. 인터넷 할당 번호 관리 기관에 의해 할당된 애플리케이션 프로토콜이 없고, 특별히 관리되지 않는 포트 번호인 만큼 자유롭게 사용할 수 있다.

 

서버로서 동작하는 프로그램은 일반적으로 잘 알려진 포트와 등록된 포트로 동작하는 경우가 많다. 즉, 서버로서 동작하는 프로그램의 포트 번호는 사전에 암묵적으로 정해진 경우가 많다. 반면에 클라이언트로서 동작하는 프로그램은 동적 포트 번호 중에서 임의의 번호가 할당되는 경우가 많다. 대표적으로 예시는 웹 브라우저이다. 웹 브라우저 프로그램에는 동적 포트 내의 임의의 포트 번호가 자동으로 할당된다. 

 

포트 번호를 통해 실행 중인 특정 애플리케이션을 식별할 수 있다. 따라서 IP 주소와 포트 번호에 대한 정보가 함께 주어지면 특정 호스트에서 실행 중인 특정 애플리케이션 프로세스를 식별할 수 있다. 일반적으로 IP 주소 : 포트 번호 형식으로 표기하는 경우가 많다. 

 

포트 기반 NAT

NAT란 IP 주소를 변환하는 기술이며, 주로 네트워크 내부에서 사용되는 사설 IP 주소와 네트워크  외부에서 사용되는 공인 IP 주소를 변환하는데 사용된다. 이러한 변환을 위해 주로 사용되는 것이 NAT 변환 테이블이다.

 

NAT 변환 테이블

NAT 변환 테이블에는 변환 대상이 되는 IP 주소 쌍이 명시되어 있다. 

네트워크 외부 네트워크 내부
1.2.3.4 192.168.0.5
1.2.3.5 192.168.0.6

위의 NAT 테이블에서 네트워크 내부에 192.168.0.5라는 사설 IP 주소를 가진 호스트가 있고, 수신지 주소가 10.11.12.13인 네트워크 외부의 호스트에게  패킷을 전송한다고 가정하자. 패킷이 NAT 기능을 갖춘 라우터를 거쳐 네트워크 외부로 나가게 되면 패킷의 송신지 주소는 네트워크 외부에서 사용되는 공인 IP 주소인 1,2,3,4가 된다. 반대로 수신지 주소가 1.2.3.4인 패킷이 네트워크 외부에서 네트워크 내부로 전송되는 상황일 때, 이 패킷의 수신지 주소는 NAT 라우터를 거쳐 192.168.0.5가 된다. 

 

위의 NAT 테이블은 변환 대상이 되는 IP 주소가 일대일로 대응되어 있다. NAT 테이블의 항목을 일대일로 대응해 NAT로 활용하는 것이 가능하기는 하지만, 이 방식만으로 많은 사설 IP 주소를 변환하기에 무리가 있다. 네트워크 내부에 사용되는 사설 IP 주소의 수만큼 공인 IP 주소가 필요하기 때문이다. 이러한 이유로 오늘날 대중적으로 활용되는 NAT는 다수의 사설 IP 주소를 그보다 적은 수의 공인 IP 주소로 변환한다. 이 과정에서 포트가 활용된다.

 

NAPT

포트 기반의 NAT를 NAPT(Network Address Port Translaton)라 한다. APT(Address Port Translation)라고 부르기도 한다. NAPT는 포트를 활용해 하나의 공인 IP 주소를 여러 사설 IP 주소가 공유할 수 있도록 하는 NAT의 일종이다. NAPT는 NAT 테이블에 변환할 IP 주소 쌍과 더불어 포트 번호도 함께 기록하고 변환한다. 

이처럼 네트워크 외부에서 사용할 IP가 같더라도 포트 번호가 다르면 네트워크 내부의 호스트를 특정할 수 있기 때문에, 다수의 사설 IP 주소를 그보다 적은 공인 IP 주소로 변환할 수 있게 된다. 즉 NAPT를 이용하면 사설 주소와 공인 주소를 N:1로 관리할 수 있다. 이러한 점에서 NAPT는 공인 IP 주소 수 부족 문제를 개선한 기술로 간주된다. 

 

💡 포트 포워딩
네트워크 내 특정 호스트에 IP 주소와 포트 번호를 미리 할당하고, 해당 IP주소:포트번호로써 해당 호스트에게 패킷을 전달하는 기능이다.
예를 들어 네트워크 내부에서 여러 호스트가 공인 IP 주소를 공유하는 상황에서 네트워크 외부에서 내부로 통신을 시작하는 상황을 가정하자. 네트워크 외부의 호스트가 네트워크 내부의 특정 호스트에게 패킷을 전송하고 싶어도, 네트워크 외부 호스트 입장에서는 어떤 IP 주소를 수신지 주소로 삼을지 결정하기 어렵다. 
이때 주로 사용되는 것이 포트포워딩이다. 특정 IP 주소와 포트 번호 쌍을 특정 호스트에게 할당한 뒤, 외부에서 통신을 시작할 호스트에게 해당 정보를 알려주면 된다.
어떤 '공인 IP 주소:접속 포트'에 접속했을 때 어떤 '사설 IP 주소: 내부 전달 포트'로 전달할 수 있다.

 

💡 ICMP
IP의 신뢰할 수 없는 전송 특성과 비연결형 전송 특성을 보완하기 위한 네트워크 계층의 프로토콜로 ICMP가 있다. ICMP는 IP 패킷의 전송 과정에 대한 피드백 메세지(ICMP 메세지)를 얻기 위해 사용하는 프로토콜이다. 

 


Ch.04-1 확인문제 1

IP와 연관된 통신 특성: 비신뢰성, 비연결형


 

4-2 TCP와 UDP

TCP 통신 단계와 세그먼트 구조

TCP는 통신하기 전에 연결을 수립하고, 통신이 끝나면 연결을 종료한다. 데이터 송수신 과정에서 재전송을 통한 오류 제어, 흐름 제어, 혼잡 제어 등의 기능을 제공한다.

TCP의 연결 수립과 종료를 이해하려면 MSS라는 단위와 TCP의 세그먼트 구조를 이해해야 한다.

MSS는 Maximum Segment Size의 약자로, TCP로 전송할 수 있는 최대 페이로드 크기를 의미한다. MSS의 크기를 고려할 때 MTU와는 다르게 TCP 헤더 크기는 제외한다. 

TCP는 기본 동작을 이해하기 위한 기본적인 필드를 기준으로 살펴보자.

  • 송신지 포트, 수신지 포트: 송신지, 수신지 애플리케이션을 식별하는 포트 번호가 명시되는 필드
  • 순서 번호: 송수신되는 세그먼트의 올바른 순서를 보장하기 위해 세그먼트 데이터의 첫 바이트에 부여되는 번호
  • 확인 응답 번호: 상대 호스트가 보낸 세그먼트에 대한 응답으로, 다음으로 수신하기를 기대하는 순서 번호가 명시된다. 
  • 제어 비트: 플래그 비트라고도 부르며, 현재 세그먼트에 대한 부가 정보
  • 윈도우: 수신 윈도우의 크기가 명시된다. 수신 윈도우는 한 번에 수신하고자 하는 데이터의 양을 말한다.

 

제어 비트

제어 비트는 기본적으로 8비트로 구성된다. 각 자리의 비트는 각기 다른 의미를 가진다.

  • ACK: 세그먼트의 승인을 나타내기 위한 비트
  • SYN: 연결을 수립하기 위한 비트
  • FIN: 연결을 종료하기 위한 비트

ACK 비트가 1로 설정된 세그먼트, SYN 비트가 1로 설정된 세그먼트, FIN 비트가 1로 설정된 세그먼트는 편의상 각각 ACK 세그먼트, SYN 세그먼트, FIN 세그먼트라 줄여서 칭하는 경우가 많다.

 

순서 번호화 확인 응답 번호

순서 번호와 확인 응답 번호는 TCP의 신뢰성을 보장하기 위해 사용되는 필드다. 

순서 번호는 세그먼트의 올바른 송수신 순서를 보장하기 위한 번호로, 세그먼트 데이터의 첫 바이트에 부여되는 번호이다. 

예를 들어 전송 계층이 응용 계층으로부터 데이터를 전달받는다면, 이는 MSS 단위로 쪼개져서 여러 세그먼트로 전송되게 된다. 처음 통신을 위해 연결을 수립한 경우, 즉 제어 비트에서 연결을 수립하기 위한 비트인 SYN 플래그가 1로 설정된 세그먼트의 경우 순서 번호는 무작위 값이 된다. 이를 초기 순서 번호라고 한다. 연결 수립 이후 데이터를 송신하는 동안 순서 번호는 송신한 바이트를 더해가는 형태로 누적값을 가진다. 즉, 초기 순서 번호 + 송신한 바이트 수가 된다.

 

확인 응답 번호는 순서 번호에 대한 응답이다. 즉, 확인 응답 번호는 수신자가 다음으로 받기를 기대하는 순서 번호이다. 일반적으로 수신한 순서 번호 + 1로 설정된다. 확인 응답 번호 값을 보내기 위해서는 제어 비트에서 승인을 나타내는 ACK 플래그를 1로 설정해야 한다. 

 

TCP 연결 수립과 종료

연결 수립: 쓰리 웨이 핸드셰이크

TCP의 연결 수립은 쓰리 웨이 핸드셰이크를 통해 이루어진다. 쓰리 웨이 핸드셰이크는 세 개의 단계로 이루어진 TCP의 연결 수립 과정이다 

 

송수신 방향 세그먼트 세그먼트에 포함된 주요 정보 비유
A → B SYN 세그먼트 클라이언트의 초기 순서 번호
1로 설정된 SYN 비트
"연결 시작합니다."
B → A SYN + ACK 세그먼트 서버의 초기 순서 번호
클라이언트가 전송한 세그먼트에 대한 확인 응답 번호
1로 설정된 SYN, ACK 비트
"확인했습니다.
연결 시작해요!"
A → B ACK 세그먼트 클라이언트의 다음 순서 번호
서버가 전송한 세그먼트에 대한 확인 응답 번호
1로 설정된 ACK 비트
"확인했습니다."

 

이때 연결을 요청하는 측의 동작을 액티브 오픈이라고 한다. 액티브 오픈은 주로 서버 - 클라이언트 관계에서 클라이언트에 의해 수행된다. 반대로 연결 요청을 받고나서 요청에 따라 연결을 수립하는 과정을 패시브 오픈이라 한다. 주로 서버에 의해 수행된다. 

 

연결 종료

쓰리 웨이 핸드셰이크를 통해 연결을 수립한 뒤 데이터 송수신이 끝났다면 연결을 종료해야한다. TCP가 연결을 종료하는 과정은 송수신 호스트가 각자 한번씩 FIN, ACK를 주고받으며 이루어진다. 

송수신 방향 세그먼트 세그먼트에 포함된 주요 정보 비유
A → B FIN 세그먼트 1로 설정된 FIN 비트 "연결 끊을게요."
B → A  ACK 세그먼트 클라이언트가 전송한 세그먼트에 대한 확인 응답 번호
1로 설정된 SYN, ACK 비트
"확인했습니다."
B → A FIN 세그먼트 1로 설정된 FIN 비트 "이제 연결을 끊어요."
A → B ACK 세그먼트 서버가 전송한 세그먼트에 대한 확인 응답 번호
1로 설정된 ACK 비트
"확인했습니다."

 

액티브 클로즈는 먼저 연결을 종료하려는 호스트에 의해 수행된다. 패시브 클로즈는 연결 종료 요청을 받아들이는 호스트에 의해 수행된다. 

 

TCP 상태

TCP는 연결형 통신과 신뢰할 수 있는 통신을 유지하기 위해 다양한 상태를 유지한다. 상태는 현재 어떤 통신 과정에 있는지를 나타내는 정보이다. TCP는 상태를 유지하고 활용한다는 점에서 스테이트풀 프로토콜이라고 한다. 

 

연결이 수립되지 않은 상태

아직 연결이 수립되지 않은 호스트는 주로 CLOSED나 LISTEN 상태를 유지하고 있다.

  • CLOSED: 아무런 연결이 없는 상태
  • LISTEN: 연결 대기 상태. 패시브 오픈 호스트는 LISTEN 상태를 유지한다. 즉, LISTEN 상태는 액티브 오픈 호스트의 연결 요청인 SYN 세그먼트를 기다리는 상태이다. 

연결 수립 상태

TCP 연결 수립 과정에서는 SYN-SENT, SYN-RECEIVED, ESTABLISHED 상태를 볼 수 있다.

  • SYN-SENT: 액티브 오픈 호스트가 SYN 세그먼트를 보낸 뒤 그에 대한 응답인 SYN + ACK 세그먼트를 기다리는 상태
  • SYN-RECEIVED: 패시브 오픈 호스트가 SYN + ACK 세그먼트를 보낸ㄴ 뒤 그에 대한 ACK 세그먼트를 기다리는 상태
  • ESTABLISHED: 연결이 확립되었음을 나타내는 상태. 데이터를 송수신할 수 있는 상태

연결 종료 상태

TCP 연결을 종료하는 과정에서는 FIN-WAIT-1, CLOSE-WAIT,  FIN-WAIT-2, LAST-ACK, TIME-WAIT, CLOSED 상태를 볼 수 있다.

  • FIN-WAIT-1: 연결 종료의 첫 단계. FIN 세그먼트로서 연결 종료 요청을 보낸 액티브 클로즈 호스트가 FIN-WAIT-1 상태로 접어든다.
  • CLOSE-WAIT: 종료 요청인 FIN 세그먼트를 받은 패시브 클로즈 호스트가 그에 대한 응답으로 ACK 세그먼트를 보낸 후 대기하는 상태
  • FIN-WAIT-2: FIN-WAIT-1 상태에서 ACK 세그먼트를 받게 되면 FIN-WAIT-2 상태가 된다. 상대 호스트의 FIN 세그먼트를 기다리는 상태이다.
  • LAST-ACK: CLOSE-WAITT상태에서 FIN 세그먼트를 전송한 뒤 이에 대한 ACK 세그먼트를 기다리는 상태
  • TIME-WAIT: 액티브 클로즈 호스트가 FIN 세그먼트를 수신한 뒤, 이에 대한 ACK 세그먼트를 전송한뒤 접어드는 상태이다. 패시브 클로즈 호스트가 마지막 ACK 세그먼트를 수신하면 CLOSED 상태로 전이하는 반면, TIME-WAIT 상태에 접어든 액티브 클로즈 호스트는 일정 시간을 기다린 뒤 CLOSED 상태로 전이한다. 
💡 TIME-WAIT가 필요한 이유?
상대 호스트가 받았어야할 마지막 ACK 세그먼트가 올바르게 전송되지 않았을 수 있기 때문이다. 마지막 ACK 세그먼트를 재전송 할 수 있기 위해 TIME-WAIT가 필요하다. 또한 한 연결을 종료하고 다른 연결을 수립하는 과정 사이에 대기 시간을 주기 위함이다. 

 

  • CLOSING: CLOSING 상태는 동시에 연결을 종료하려할 때 전이되는 상태이다. 서로가 FIN 세그먼트를 보내고 받은 위 각자 그에 대한 ACK 세그먼트를 보냈지만, 아직 자신의 FIN 세그먼트에 대한 ACK를 받지 못했을 때 접어드는 상태이다. 이 경우 ACK 세그먼트를 수신한다면 TIME-WAIT 상태로 접어든위 종료하게 된다. 

 

UCP 데이터그램 주소

UDP는 TCP와는 달리 비연결형 통신을 수행하는 신회할 수 없는 프로토콜이다. 연결 수립 및 해제, 재전송을 통한 오류 제어, 혼잡 제어, 흐름 제어 등을 수행하지않는다. 상태를 유지하지도, 활용하지도 않는다는 점에서 UDP를 스테이트리스 프로토콜의 일종이라고 한다. 

 

UDP 데이터 그램 헤더는 송신지 포트와 수신지 포트, 길이, 체크섬 필드의 네 개의 필드로 구성되어 있다. 

  • 송신지 포트수신지 포트: 송수신지의 포트 번호
  • 길이: 헤더를 포함한 UDP 데이터그램의 바이트
  • 체크섬: 데이터그램 전송 과정에서 오류가 발생했는지 검사하기 위한 필드.이 필드의 값을 토대로 정보가 훼손되었다고 판단하면 데이터그램을 폐기한다. 

UDP는 TCP에 적은 오버헤드로 패킷을 빠르게 처리할 수 있다. 그래서 주로 실시간 스트리밍 서비스, 인터넷 전화처럼 실시간성이 강조되는 상황에서 많이 쓰인다. 


Ch.04-2 확인문제 2

ACK 세그먼트 → 서버가 전송한 세그먼트에 대한 확인 응답 번호, 1로 설정된 ACK 비트가 포함된다.


 

4-3 TCP의 오류, 흐름, 혼잡 제어

TCP는 재전송을 기반으로 다양한 오류를 제어하고, 흐름 제어를 통해 처리할 수 있을 만큼만의 데이터 만들 주고받으며, 혼잡 제어를 통해 네트워크가 혼잡한 정도에 따라 전송량을 조절한다.

 

오류 제어: 재전송 기법

TCP는 잘못된 세그먼트를 재전송하는 방법을 사용한다.

 

오류 검출과 재전송

체크섬은 세그먼트의 훼손 여부만 나타낼 뿐이고, 체크섬을 이용한다고 해도 송신 호스트가 세그먼트 전송 과정에 문제가 있다는 것을 인지할 수는 없다. TCP가 신뢰성을 제대로 보장하려면 우선 송신 호스트가 송신한 세그먼트에 문제가 발생했음을 인지할 수 있어야하고, 오류를 감지하게 되면 해당 세그먼트를 재전송할 수 있어야한다. 

 

TCP가 송신한 세그먼트에 문제가 있음을 감지하는 상황은 크게 두가지이다. 하나는 중복된 ACK 세그먼트를 수신했을 떄이고, 다른 하나는 타임아웃이 발생했을 때이다.

 

1. 중복된 ACK 세그먼트를 수신했을 때

우선 호스트 A와 B가 올바르게 세그먼트를 주고받는다면, A는 첫 순서 번호를 담은 세그먼트를 보내고, 그에 대한 ACK 세그먼트를 받은 뒤에 다음 순서를 담은 세그먼트를 보내고 그에 대한 ACK 세그먼트를 받는 것을 반복한다.

만일 수신 호스트 측이 받은 세그먼트의 순서 번호 중에 일부가 누락되었다면 중복된 ACK 세그먼트를 전송하게 된다. 

 2. 타임아웃이 발생했을 때

TCP는 타임아웃이 발생하면 문제가 생겼음을 인지한다. TCP 세그먼트를 송신하는 호스트는 모두 재전송 타이머라는 값을 유지한다. 호스트가 세그먼트를 전송할 때마다 재전송 타이머를 시작하게 되는데, 이 타이머의 카운트다운이 끝난 상황을 타임아웃이라 한다. 타임아웃이 발생할 때까지 ACK 세그먼트를 받지 못하면 세그먼트가 상태 호스트에 정상적으로 도착하지 않았다고 간주하여 세그먼트를 재전송한다. 

 

ARQ: 재전송 기법

수신 호스트의 답변(ACK)과 타임아웃 발생을 토대로 문제를 진단하고, 문제가 생긴 메세지를 재전송함으로써 신뢰성을 확보하는 방식을 ARQ(Automatic Repeat Request, 자동 재전송 요구)라고 한다. 가장 대표적인 세 가지 방식은 Stop-and-Wait ARQ와 Go-Back-N ARQ 그리고 Selective Repeat ARQ가 있다. 

 

Stop-and-Wait ARQ

Stop-and-Wait ARQ는 제대로 전달했음을 확인하기 전까지 새로운 메세지를 보내지 않는 방식이다. 즉, 메세지를 송신하고, 이에 대한 확인 응답을 받고 다시 메세지를 송신하고, 이에 대한 확인 응답을 받는 것을 반복한다. 

하지만 이 방식은 송신 호스트 입장에서 다음 전송을 할 수 있어도 확인 응답을 받기 전까지는 보낼 수 없다. 따라서  네트워크의 이용 효율이 낮아질 수 있다. 

 

Go-Back-N ARQ

Stop-and-Wait ARQ의 문제를 해결하려면 ACK 세그먼트가 도착하기 전에 여러 세그먼트를 보낼 수 있어야 한다. 이렇게 연속해서 메세지를 전송할 수 있는 기술은 파이프라이닝이라고 한다. Go-Back-N ARQ, Selective Repeat ARQ이 파이프라이닝을 기반으로 동작한다. 

Go-Back-N ARQ은 파이프라이닝 방식을 활용해 여러 세그먼트를 전송하고, 도중에 잘못 전송된 세그먼트가 발생할 경우 해당 세그먼트부터 전부 다시 전송하는 방식이다. 송신 호스트 입장에서는 N번 세그먼트에 대한 ACK 세그먼트를 받지 못했기에 타임아웃이 발생하고, 이를 통해 송신 호스트는 잘못된 송신이 있음을 인지한다.따라서 ACK 세그먼트를 수신받지 못한 N번째 세그먼트부터 다시 전송하게 된다.

이런 점에서 볼때 Go-Back-N ARQ에서 N번에 대한 ACK 세그먼트는 N번까지의 확인 응답이라고 볼 수 있다. 따라서 ACK 세그먼트를 누적 확인 응답이라고 한다.

 

Selective Repeat ARQ 

Selective Repeat ARQ는 선택적으로 재전송하는 방법이다. Selective Repeat ARQ는 수신 호스트 측에서 제대로 전송받은 각각의 패킷들에 대해  ACK 세그먼트를 보내는 방식이다.따라서 Selective Repeat ARQ의 ACK 세그먼트는 개별 확인 응답이다. 송신 호스트는 올바르게 수신받지 못한 ACK 세그먼트가 있는지 검사하고, 만일 받지 못한 세그먼트가 존재한다면 해당 세그먼트를 재전송한다. 오늘날 대부분의 호스트는 TCP 통신에서 Selective Repeat ARQ을 지원한다.

 

흐름 제어: 슬라이딩 윈도우

파이프라이닝 기반의 Go-Back-N ARQ와 Selective Repeat ARQ가 정상적으로 동작하려면 반드시 흐름 제어를 고려해야한다. 호스트가 한 번에 받아서 처리할 수 있는 세그먼트의 양에 한계가 있기 때문이다. 예를 들어 수신 호스트가 한 번에 n개의 바이트를 받아서 처리할 수 있다면, 송싱 호스트는 이 점을 인지하여 n개 바이트를 넘지 않는 선에서 송신해야 한다. 

 

수신 버퍼는 수신된 세그먼트가 애플리케이션 프로세스에 의해 읽히기 전에 임시로 저장되는 공간이다. 송신 호스트가 흐름제어를 고려하지 않고 수신 버퍼 크기보다 많은 데이터를 전송하면 일부 세그먼트가 처리되지 않을 수 있다. 이렇게 버퍼가 넘치는 문제 상황을 버퍼 오버플로라고 한다. TCP의 흐름 제어는 이러한 문제 상황을 방지하고자 송신 호스트가 수신 호스트의 처리 속도를 고려하며 송수신 속도를 유지하는 것을 의미한다.

 

오늘날 TCP에서는 흐름 제어로 슬라이딩 윈도우 방식을 사용한다. 윈도우란 송신 호스트가 파이프라이닝할 수 있는 최대량을 말한다. 윈도우 크기만큼 확인 응답을 받지않고도 한 번에 전송 가능하다는 의미이다. 송신 호스트는 윈도우의 크기만큼 전송하고, 첫번째 세그먼트에 대한 ACK를 받으면 윈도우를 오른쪽으로 한 칸 이동하게 된다. 

송신 윈도우는 수신 호스트가 알려주는 수신 윈도우를 토대로 알 수 있는 정보이다. 수신 호스트가 한번에 수신하고자 하는 데이터의 양 만큼 전송해야하기 때문이다. 따라서 수신 호스트는 TCP 헤더의 윈도우 필드를 통해 송신 호스트에게 윈도우를 알린다. 송신 호스트는 이 정보를 바탕으로 수신 호스트의 처리 속도에 맞게 세그먼트를 전송하게 된다. 

 

혼잡 제어

혼잡 제어를 수행하는 송신 호스트는 네트워크 혼잡도를 판단하고, 혼잡한 정보에 맞춰 유동적으로 전송량을 조절하며 전송한다. 혼잡 윈도우는 혼잡없이 전송할 수 있을 법한 데이터양을 의미한다. 송신 호스트 입장에서 생각해보면 수신 윈도우 크기는 수신 호스트가 TCP 헤더로 알려주기에 별다른 고민이 없지만, 혼잡 위도우는 송신 호스트가 어느 정도의 세그먼트를 전송해야 혼잡을 방지할 수 있을지를 직접 계산하여 알아내야 한다. 

혼잡 윈도우 크기는 혼잡 제어를 수행하는 일련의 방법인 혼잡 제어 알고리즘을 통해 결정할 수 있다. 기본적인 알고리즘은 AIML는 Additive Increase/Multiplicative Decrease의 약자로, 해석하면 합으로 증가, 곱으로 감소하는 의미다. 혼잡이 감지되지 않는다면 혼잡 윈도우를 RTT마다 1씩 선형적으로 증가시키고, 혼잡이 감지되면 혼잡 윈도우를 절반으로 떨어뜨리는 동작을 반복하는 알고리즘이다. AIMD를 더 정교하게 만들 혼잡 제어 알고리즘으로 는 느린 시작, 혼잡 회피, 빠른 회복이 있다.

💡 RTT : 메세지를 전송한 뒤 그에 대한 답변을 받는데까지 걸리는 시간

 

느린 시작 알고리즘

느린 시작 알고리즘은 혼잡 윈도우를 1부터 시작해 문제없이 수신된 ACK 세그먼트 하나당 1씩 증가시키는 방식이다.결과적으로 혼잡 윈도우는 RTT마다 2배씩 지수적으로 증가하게 된다. AIMD 방식은 처음 연결이 수립된 뒤 혼잡 윈도우 크기가 증가되는 속도가 느리다. 선형적으로 혼잡 윈도우를 증가시키기 때문이다. 하지만 느린 시작을 이용하면 혼잡 윈도우의 지수적인 증가를 활용해 초기 전송 속도를 어느정도 빠르게 확보할 수 있다.

느린 시작 알고리즘은 함께 사용하는 값으로 느린 시작 임계치라는 값이 정해져 있다. 혼잡 윈도우 값이 계속 증가하다 느린 시작 임계치 이상이 되거나 타임아웃이 발생하거나, 세번의 중복된 ACK 세그먼트가 발생하여 혼잡이 감지되면 특정 방법을 수행한다.

상황 분류 방법
타임 아웃 발생 혼잡 윈도우 값을 1로, 느린 시작 임계치를 혼잡이 감지되었을 시점의 혼잡 윈도우 값의 절반으로 초기화한 뒤 느린 시작 재개
혼잡 윈도우 >= 느린 시작 임계치 느린 시작 종료, 혼잡 윈도우를 절반으로 초기화한 뒤 혼잡 회피 수행
세 번의 중복 ACK 발생 빠른 재전송 후 빠른 회복 수행

 

혼잡 회피 알고리즘

혼잡 회피 알고리즘은 RTT마다 혼잡 윈도우를 1MSS씩 증가시키는 알고리즘이다. 느린 시작 임계치를 넘어선 시점부터 혼잡이 발생할 우려가 있으니 조심해서 혼잡 윈도우를 증가시키는 방식이다.

이때 혼잡 회피 도중 타임아웃이 발생하면 혼잡 윈도우 값은 1로, 느린 시작 임계치는 혼잡이 감지된 시점의 윈도우 값의 절반으로 초기화한 뒤 느린 시작을 수행한다. 혼잡 회피 도중 세 번의 중복 ACK 세그먼트가 발생했을 때는 혼잡 윈도우 값과 느린 시작 임계치를 대략 절반으로 떨어뜨린 뒤 빠른 회복 알고리즘을 수행한다. 

 

빠른 회복 알고리즘

빠른 회복 알고리즘은 세번의 중복 ACK 세그먼트를 수신했을 때 느린 시작은 건너뛰고 혼잡 회피를 수행하는 알고리즘으로, 빠르게 전송률을 회복하기 위한 알고리즘이다. 단 빠른 회복 도중이라도 타임아웃이 발생하면 혼잡 윈도우 크기는 1로,  느린 시작 임계치는 혼잡이 감지된 시점의 절반으로 떨어뜨린 후 다시 느린 시작을 수행한다.


추가숙제

작업 관리자에서 프로세스별 PID 확인해 보기

  • 윈도우의 작업 관리자 창에서 세부정보를 클릭하면 확인 가능하다.