首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

TCP/IP 協議設計:單包封裝多字段,TLV 格式與解析邏輯

     編輯:程式設計綜合問答

場景

註冊/登錄請求包含:用戶名(必填)、密碼(必填)、手機號(選填)等若干字段。一次性打包發送,還是分多包?

結論:單包封裝所有字段

優點:原子性、減少網絡往返、避免半狀態、簡化服務端狀態機。

推薦編碼:TLV (Type-Length-Value) / 簡化版

// 結構定義
struct Field {
    uint16_t tag;    // 字段標識:1=用戶名, 2=密碼, 3=手機號, 4=邮箱...
    uint16_t len;    // 值長度 (字節數)
    char     val[];  // 值內容 (不含結束符)
};

// 完整報文:[Field1][Field2][Field3]... 末尾可加 0x0000 標記結束
// 例:用戶名="wang"(4字節), 密碼="ab12345"(7字節), 手機號="12345678910"(11字節)
// 0x0001 0x0004 'w''a''n''g' 0x0002 0x0007 'a''b''1''2''3''4''5' 0x0003 0x000B '1''2''3''4''5''6''7''8''9''1''0'

服務端解析邏輯

void parsePacket(const char *buf, size_t len) {
    size_t offset = 0;
    while (offset + 4 <= len) {
        uint16_t tag = ntohs(*(uint16_t*)(buf + offset));
        uint16_t flen = ntohs(*(uint16_t*)(buf + offset + 2));
        if (tag == 0 && flen == 0) break; // 結束標記
        if (offset + 4 + flen > len) { /* 截斷錯誤 */ break; }
        const char *val = buf + offset + 4;
        switch (tag) {
            case 1: username = string(val, flen); break;
            case 2: password = string(val, flen); break;
            case 3: phone = string(val, flen); break;
            default: /* 忽略未知字段,兼容擴展 */ break;
        }
        offset += 4 + flen;
    }
}

優勢

  • 自描述:無需固定順序,字段可選、可擴展、版本兼容。
  • 二進制高效:無 JSON/XML 文本解析開銷,適合高性能場景。
  • 長度前置:支持包含 \0 的二進制數據 (如密碼哈希、圖片)。

替代方案

  • Protocol Buffers / FlatBuffers / MessagePack:成熟序列化框架,自動生成代碼,強烈推薦新項目使用。
  • JSON over TCP:調試方便,但需處理粘包 (長度前綴/分隔符),性能稍遜。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved