LODY/정리

컴퓨터 네트워크 / TCP 프레이밍

TCP 프레이밍

개요

항목내용
TCP가 보장하는 것순서 있는 바이트 스트림 (신뢰성, 순서)
TCP가 보장하지 않는 것send 단위 = 수신 recv 단위. 메시지(프레임) 경계
애플리케이션의 역할스트림에서 한 메시지의 시작·끝을 규칙으로 정의 → 프레이밍(Framing)

send를 여러 번 호출해도 수신 측은 한 번에 이어붙인 덩어리로 받을 수도, 임의로 쪼개서 받을 수도 있음. Nagle, 세그먼트 분할 등은 TCP 내부 동작.


1. 구분자 (Delimiter)

형태: 본문 뒤에 고정 바이트 시퀀스로 끝맺음.

[페이로드][구분자]

HTTP/1.1 예: 요청/응답 헤더는 \r\n\r\n 종료, 바디는 Content-Length 등으로 길이.

이점구현 난이도 낮음
제약본문에 구분자와 같은 바이트가 나오면 이스케이프·이스케이프 해제 규칙 필요
바이너리구분자가 데이터 안에 자연스럽게 나타날 수 있어 비권장에 가까움

2. 길이 프리픽스 (Length-Prefix)

형태: 페이로드 길이를 헤더에 두고, 그다음에 N바이트를 본문으로 읽기.

[길이 필드(고정 비트/바이트)][N바이트 페이로드]

수신 절차 (예: 길이 4바이트)

  1. 길이 필드 N바이트(예: 4) 완전히 읽기
  2. N을 정수로 해석한 뒤, 그 횟수만큼 본문 읽기

페이로드에 어떤 바이트 패턴도 올 수 있음 — 경계는 길이 필드에만 의존.

확장: 타입(명령 코드) 1바이트 + 길이 4바이트 + 본문 등, 헤더를 고정 길이로 잡는 패턴.


3. 엔디안 (길이·정수 필드)

정수 1000 (0x000003E8)의 바이트 나열:

순서예시(16진)
Big Endian상위 바이트 선행00 00 03 E8
Little Endian하위 바이트 선행E8 03 00 00
  • 대부분의 일반 PC·모바일 CPU(ARM, x86): Little Endian이 기본.
  • IETF/RFC 맥락의 "네트워크 바이트 순서": Big Endian (RFC 1700 등에서 Network Byte Order로 통용).

중요: 송수신 코드에서 UInt32를 그냥 메모리에 붙이면(플랫폼 엔디안) 상호운용 시 길이 값 깨짐. Swift 예시는 bigEndian / init(bigEndian:)명시적 변환.

// 송신: 로컬 정수 → 네트워크(빅엔디안) 바이트
var length = UInt32(payload.count).bigEndian
data.append(Data(bytes: &length, count: 4))
 
// 수신: 네트워크(빅엔디안) 바이트 → 로컬
let length = UInt32(bigEndian: data[0..<4].withUnsafeBytes {
    $0.load(as: UInt32.self)
})

(위 data[0..<4]길이 필드가 페이로드 앞 4바이트인 경우. 헤더에 타입 1 + 길이 4이면 data[1..<5]로 오프셋 조정.)


4. 수신: 부분 recv와 루프

길이 프리픽스 기준 최소 2단계: (1) 헤더 고정 길이, (2) length만큼 본문.

  • recv(n)한 번에 n바이트를 보장하지 않음. 부분 수신.
def recv_exact(sock, n):
    data = b''
    while len(data) < n:
        chunk = sock.recv(n - len(data))
        if not chunk:
            raise ConnectionError("connection closed")
        data += chunk
    return data
 
# 예: type 1 + length 4
header = recv_exact(sock, 5)
msg_type = header[0]
length = int.from_bytes(header[1:5], 'big')
payload = recv_exact(sock, length)

5. 방식 비교

DelimiterLength-Prefix
구현단순고정 헤더 + recv_exact 수준
바이너리 페이로드이스케이프 부담길이만 맞으면 무방
HTTP/1.1 헤어 종료, 일부 텍스트 프로토콜gRPC(상위), 커스텀 바이너리, 게임/임베디드

용어

  • Framing: TCP 스트림 위에 애플리케이션이 정의한 메시지 경계 규칙.
  • Nagle: 작은 전송을 묶는 TCP 옵션. send 호출 횟수와 TCP 세그먼트 1:1이 아님.
  • Network Byte Order: 프로토콜에서 쓰는 빅엔디안 정수 표기.
  • Length-Prefix Framing: 앞에 길이, 뒤에 N바이트 본문.