TCP와 UDP
전송계층이란?
- 네트워크 계층과 응용 계층 사이에 존재하는 통신 계층.
- 네트워크 계층의 프로토콜이 가지고 있던 약점을 보완.
- 응용계층의 하위 계층으로서 그 기반 역할을 수행.
전송계층의 필요성
IP는 호스트에서 호스트까지 패킷을 전송은 하지만, 특정 어플리케이션에 패킷이 전송 되었는지는 보장하지 않습니다.
중간에 패킷이 손실되거나 잘못 전송되어도 이를 확인하거나 복구할 기능이 포함되어 있지 않습니다. 물론 이런 방식이 마냥 나쁜 것만은 아닙니다. 동영상 스트리밍처럼 때론 신뢰성보다도 속도가 더 중요할 때도 있기 때문입니다.
따라서 IP의 상위 계층인 전송 계층에서는 두 가지 종류의 통신을 지원하는데요. 하나는 TCP 통신이고, 또 하나는 UDP 통신입니다. TCP는 신뢰할 수 있는 통신과 연결형 통신을 지원하고, UDP는 신뢰할 수 없고 비연결형 통신이지만, 비교적 빠른 전송을 가능케 합니다.
소켓 프로그래밍
TCP와 UDP는 소켓이라는 인터페이스, 쉽게 말해 논리적 연결부를 통해 메시지를 송수신합니다.
소켓에는 두 가지 본질적인 타입이 존재합니다. 앞서 언급한 TCP와 UDP입니다. 애플리케이션은 소켓을 생성하고, 소켓의 타입에 의해 소통 방식이 결정됩니다.(reliable vs. best effort / connection-oriented vs. connectionless)
(1) SOCK_STREAM(소켓 스트림) => TCP
- reliable delivery
- 순서 보장
- 연결 지향성
- 양방향 통신
(2) SOCK_DGRAM(소켓 데이터그램) => UDP
- unreliable delivery
- 순서 보장하지 않음
- 연결에 대한 개념이 존재하지 않음(애플리케이션은 각 데이터그램마다 도착지 정보를 가르쳐줄 뿐)
- 송수신이 가능하지만 독립적인 데이터그램 단위에서 이루어진다.(연결이 이루어지는 TCP의 양방향 통신과는 조금 다름)
즉, 애플리케이션 계층이 소켓으로 통신을 하는 이유는 순전히 전송계층에서 이를 필요로하기 때문입니다.
만약 소켓이 스트림 타입이라면 TCP 통신이 이루어질 테고 우리가 흔히 알고 있는 TCP 연결 수립 과정이 이루어집니다. 3 웨이 핸드셰이크 방식이죠.
출처 : https://github.com/Seogeurim/CS-study/blob/main/contents/network/img/3-way-handshake.png?raw=true
클라이언트가 SYN 플래그를 1로 설정하고 패킷을 보내면 서버가 ACK와 SYN 패킷을 보내 연결을 허락합니다. 클라이언트가 서버의 응답을 받고 ACK 패킷을 보내면 두 소켓 간에 논리적인 연결이 수립됩니다.
3-Way HandShake
- A(CLOSED) → B(LISTEN) : SYN(a)
- 프로세스 A가 연결 요청 메시지 전송 (SYN)
- 이 때 Sequence Number를 임의의 랜덤 숫자(a)로 지정하고, SYN 플래그 비트를 1로 설정한 segment를 전송한다.
- B(SYN_RCV) → A(CLOSED) : ACK(a+1), SYN(b)
- 연결 요청 메시지를 받은 프로세스 B는 요청을 수락(ACK)했으며, 요청한 A 프로세스도 포트를 열어달라(SYN)는 메시지 전송
- 받은 메시지에 대한 수락에 대해서는 Acknowledgement Number 필드를 (Sequence Number + 1)로 지정하여 표현한다. 그리고 SYN과 ACK 플래그 비트를 1로 설정한 segment를 전송한다.
- A(ESTABLISHED) → B(SYN_RCV) : ACK(b+1)
- 마지막으로 프로세스 A가 수락 확인을 보내 연결을 맺음 (ACK)
- 이 때, 전송할 데이터가 있으면 이 단계에서 데이터를 전송할 수 있다.
최종 PORT 상태 : A-ESTABLISHED, B-ESTABLISHED (연결 수립)
TCP가 가진 기능 중에 애플리케이션을 식별하는 것 외에도 중요한 것이 크게 세 가지가 있습니다. 오류 제어, 흐름 제어, 혼잡 제어입니다. 이 세 역할에 대해 설명드리기 앞서 TCP 프로토콜의 데이터 전송 단위인 세그먼트의 구조에 대해 간략하게 말씀을 드리고 넘어가겠습니다.
TCP 세그먼트 구조
TCP 세그먼트에는 다양한 제어비트 필드와 순서 번호 필드, 그리고 확인 응답 번호 필드가 존재합니다.
- 제어 비트는 앞서 쓰리 웨이 핸드셰이크에서 말씀드렸던 것처럼 SYN, ACK, FIN 등등 TCP 연결과 세그먼트 승인을 위한 비트 필드, 쉽게 말해 플래그입니다.
- 순서 번호는 세그먼트의 올바른 송수신 순서를 보장하기 위한 번호로, 세그먼트 데이터의 첫 바이트에 부여되는 번호입니다.
맨 처음에, 그러니까 TCP 연결을 수립하기 위해 SYN 플래그를 1로 변경해서 보낸다고 했는데요. 이 경우 초기 순서 번호로 랜덤한 값으로 가지게 됩니다. 그리고 그 다음 세그먼트의 순서 번호는 초기 순서 번호에다가 송신한 바이트를 더해 가면서 누적값을 가지게 됩니다.
- 확인 응답 번호는 순서 번호에 대한 응답입니다. “다음에는 이걸 보내 주세요"를 나타내는 값입니다. 일반적으로 순서 번호 + 1로 설정합니다.
TCP 오류 제어
그런데 만약 전송 과정에 문제가 생긴다면, 순서 번호가 n번째인 패킷을 보냈는데 n+1번째 확인 응답이 안 오는 경우가 있을 수 있습니다. 혹은 n번째 패킷을 이미 보냈음에도 수신 측에서 계속 n+1번째 패킷을 달라고 확인 응답을 중복해서 보낼 수도 있습니다. 이런 경우 TCP는 재전송 기반으로 오류 제어를 하게 됩니다. 이런 기법을 ARQ라고 부르는데요. ARQ에도 몇 가지 종류가 있습니다.
Stop and Wait ARQ : 제대로 전달되었음을 확인 응답을 받을 때까지 그 다음 메시지를 아예 보내지 않습니다. 높은 신뢰성을 가지지만 그만큼 효율이 낮아서 성능이 저하됩니다.
-> 그래서 현실적으로 자주 사용되는 방식은 이 Stop and Wait ARQ가 아니라 연속적으로 메시지를 보내는 파이프라이닝 방식을 취하게 됩니다.
Go Back N ARQ : 파이프라이닝을 기반으로 합니다. n부터 n+10까지 세그먼트를 보낼 때 오류가 발생하면 해당 세그먼트부터 전부 재전송을 하는 방식입니다. 즉 순서 번호 n에 대한 확인 응답이 아닌 n까지 누적된 확인 응답을 보낸다고 볼 수 있습니다.
Selective Repeat ARQ : 역시 파이프라이닝을 기반으로 합니다. 반대로 Selective Repeat ARQ는 개별적인 확인 응답 번호를 보내주기 때문에 n+2번째 세그먼트가 누락되었다면 해당하는 세그먼트만 골라서 재전송을 하게 됩니다.
TCP 흐름제어
하지만 파이프 라이닝을 통해 메시지를 연속적으로 보내기 위해선 고려해야 하는 점이 있습니다. 바로 수신 호스트가 한 번에 얼마만큼의 데이터를 처리할 수 있는지를 파악하는 것입니다. 물리적으로 그 양에는 한계가 있을 수밖에 없기 때문입니다.
출처: TCP Sliding Window - Famous Security Blog
TCP의 흐름 제어 기법에서 송신 호스트가 파이프라이닝할 수 있는 처리량을 윈도우라고 부릅니다. 수신 측 헤더에 적혀있는 이 윈도우 사이즈를 바탕으로, 송신측은 윈도우를 슬라이딩 형식으로 한 세그먼트씩 이동시키면서 메시지를 전송하게 됩니다.
TCP 혼잡제어
혼잡 제어에서도 마찬가지로 혼잡 윈도우라는 걸 사용하는데요. 다만 이 경우엔 호스트와 호스트 간의 데이터 처리량을 고려하는 게 아니라 호스트와 네트워크 간에 주고 받을 수 있는 세그먼트의 양을 고려하게 됩니다. 수신 윈도우의 경우는 수신 호스트가 헤더를 통해 알려주지만 혼잡 윈도우는 송신 측에서 알아서 계산해야 합니다.
이 계산을 위해 가장 기본적으로 쓰이는 알고리즘이 AIMD인데요. 보내는 패킷의 양을 일정한 방식으로 증가시키다가 혼잡이 감지되면 혼잡 윈도우의 크기를 적절하게 줄이는 방식입니다.
느린 시작 알고리즘의 경우 혼잡 윈도우를 1부터 시작해서 2배씩 증가시킵니다. 그러다가 임계치에 다다르면 혼잡 회피 알고리즘을 수행합니다. 타임아웃이 발생하면 느린 시작을 아예 새로 시작합니다. 중복된 확인 응답을 수신하면 빠른 회복 알고리즘을 수행하게 됩니다.
여기서 혼잡 회피 알고리즘이란, 2배씩 증가시키던 혼잡 윈도우의 양이 임계치에 다다르면, 다시 선형적으로 증가시키는 방식입니다. 빠른 회복 알고리즘도 마찬가지로 혼잡 회피 알고리즘을 수행하는데 만약 중복 응답을 또 다시 받게 되면 타임아웃과 마찬가지로 다시 느린 시작을 수행합니다.
UDP
- User Datagram Protocol의 약자로 데이터를 데이터그램 단위로 처리하는 프로토콜
- 비연결형, 신뢰성 없는 전송 프로토콜(TCP처럼 Handshake 절차가 필요하지 않다.)
- TCP에서 지원하는 흐름제어, 혼잡제어, 순서보장, 전송보장 기능을 제공하지 않음
사용목적
- 신속한 데이터 전송을 위해(낮은 오버 헤드)
- 패킷이 순서가 뒤바뀌거나 유실되어도 상관 없는 정보일 때
헤더 구조
필드 | 크기(비트) | 설명 |
Source Port | 16 | 송신자의 포트 번호 |
Destination Port | 16 | 수신자의 포트 번호 |
Length | 16 | UDP 헤더 + 데이터의 길이 |
Checksum | 16 | 오류 검출을 위한 체크섬 |
'개발일지 > TIL(Today I Learned)' 카테고리의 다른 글
2025-02-24 <최종프로젝트 D-18> 채팅 기능 업그레이드 (0) | 2025.02.24 |
---|---|
2025-02-21 <최종 프로젝트 D-21> (0) | 2025.02.21 |
2025-02-19 <최종프로젝트 D-23> (0) | 2025.02.19 |
2025-02-18 <최종 프로젝트 D-24> (0) | 2025.02.18 |
2025-02-17 (0) | 2025.02.17 |
댓글