---
title: 二进制协议设计
url: https://doc.liz6.com/networking/14-protocol-design-and-evolution/01-binary-protocol-design
locale: zh
area: networking
tags:
- networking
- 协议设计与演进
date: 2026-06-30
modified: 2026-06-30
description: 二进制协议比文本协议更紧凑,但每个设计决策——framing(length-prefixed vs delimiter)、整数编码(varint vs fixed)、可扩展性(TLV 让 parser 跳过未知字段)——都影响协议的带宽效率、解析复杂度和向前兼容能力。Protobuf 的 wire format 是这…
---

# 二进制协议设计

> 二进制协议比文本协议更紧凑,但每个设计决策——framing(length-prefixed vs delimiter)、整数编码(varint vs fixed)、可扩展性(TLV 让 parser 跳过未知字段)——都影响协议的带宽效率、解析复杂度和向前兼容能力。Protobuf 的 wire format 是这些决策的经典参考。

## 概述

二进制协议比文本协议更紧凑，但需要仔细设计字段编码和扩展性。核心决策：framing 方式（length-prefixed vs delimiter）、整数编码（varint vs fixed-width）、可扩展性（TLV 让 parser 跳过未知字段）。Protobuf（Google, 2008）广泛用于微服务通信和配置序列化，其 wire format 设计——field number + wire type tag + varint/length-delimited data——是二进制协议的优秀范例。

## Framing

```
Length-prefixed:
  [4-byte len (big-endian)][payload]
  优点: 简单, 读取 len → 分配 buffer → 读 payload
  缺点: 需要预知长度

Delimiter-based:
  [payload][CR LF CR LF]  ← HTTP header boundary
  [payload][CR LF . CR LF] ← SMTP body end
  → 需要 escaping when delimiter appears in payload
```

## TLV (Type-Length-Value)

可扩展性: parser 不认识 type → skip by length → forward compatible

```
[Type (1-2B)] [Length (1-4B)] [Value (length bytes)]
```

## 整数编码

```
Fixed: 2/4/8B big-endian (IP, TCP, DNS)

varint (protobuf, QUIC):
  每 byte 最高 bit = "后续还有"
  例: 300 = 0x12C → 1010 1100 0000 0010 = AC 02 (2B)

ZigZag (signed int):
  sint32: 0→0, -1→1, 1→2, -2→3 → 小绝对值的小编码
```

## Protobuf Wire Format

```
field = (field_number << 3) | wire_type

wire_type: 0=varint, 2=length-delimited

message Person {
  string name = 1;  → tag: 0x0A (1<<3 | 2), len, UTF-8 bytes
  int32  age  = 2;  → tag: 0x10 (2<<3 | 0), varint
}
```

## Byte Order

```
Big-endian (网络字节序): TCP/IP headers → htons() / htonl()
Little-endian (主机): x86/ARM → 新协议用 LE (CPU native, 少转换)
```

## 参考

- **protobuf**: protobuf.dev/programming-guides/encoding
- **QUIC**: RFC 9000 (varint encoding in Appendix A)

*Keywords: framing, TLV, varint, protobuf, big-endian, little-endian, ZigZag*
