首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言通信協議設計與單元測試實戰指南

     編輯:關於C語言

前言:軟體模組間溝通的基石

在實際的軟體開發專案中,多模組協作是常態。不同模組之間若要實現高效、可靠的通信,必須遵循共同的訊息規範——這就是「通信協議」。本文將透過實際 C 語言程式碼範例,深入淺出地講解如何定義協議結構、實作訊息解析邏輯,並完整示範單元測試的設計與執行流程,為嵌入式與系統級開發工程師提供實戰參考。

一、 什麼是軟體模組間的協議?

簡單來說,協議就是模組之間「說話」的共同語言。一條完整的訊息通常由訊息頭和訊息體兩部分組成:

  • 訊息頭:負責標識訊息類型,讓接收端能快速識別並分發處理。
  • 訊息體:承載實際的業務數據內容。

完整訊息結構示意圖

圖1 一條完整的訊息結構示意圖

在 C 語言中,我們習慣使用 struct 結構體來映射協議格式,方便記憶體對齊與直接存取。

二、 單元測試核心觀念

單元測試是程式碼交付前的關鍵防線。它針對單一函數,驗證「給定特定輸入,是否產生預期輸出」。測試過程可視為一個「灰盒」:輸入測試資料,觀察輸出結果,不關心內部實現細節。

單元測試示意圖

圖2 單元測試示意圖

完整的測試用例應包含:測試目的、預置條件、測試步驟、預期結果、通過準則及測試工具等要素。

三、 實戰協議定義與擴展設計

本範例定義了一個用戶請求訊息 UserReqMsg_T,包含 4 個保留字段的訊息頭,以及 5 個業務字段的訊息體:

// 訊息頭結構
typedef struct {
    UINT16 iReserve1;
    UINT16 iReserve2;
    UINT16 iReserve3;
    UINT16 iReserve4;
} MsgHead_T;

// 完整訊息結構體
typedef struct {
    MsgHead_T MsgHead;           // 訊息頭
    UINT32 iOperType;            // 操作類型 (僅允許 1 或 2)
    UINT8 szUserNumber[30];      // 用戶號碼
    UINT8 szOperTime[20];        // 操作時間 (格式: yyyymmdd)
    UINT32 iReserve1;            // 保留字段1
    UINT8 szReserve2[50];        // 保留字段2
} UserReqMsg_T;

設計亮點: 預留字段是為了未來協議升級擴展而保留的「彈性空間」。當新增業務欄位時,無需修改協議結構版本,直接復用保留字段即可,極大降低了維護成本與相容性風險。

四、 核心程式碼實作

程式主流程:初始化訊息頭 → 從標準輸入讀取業務字段 → 調用驗證函數 ProcUserReqMsg → 根據返回值輸出結果或錯誤資訊。

INT32 ProcUserReqMsg(UserReqMsg_T *ptUserReqMsg) {
    // 1. 空指標防護
    if (ptUserReqMsg == NULL) return -1;

    // 2. 業務規則校驗
    if ((ptUserReqMsg->iOperType != 1) && (ptUserReqMsg->iOperType != 2)) return -2; // 操作類型非法
    if (strlen(ptUserReqMsg->szUserNumber) != 8) return -3;                          // 號碼長度異常
    if (strlen(ptUserReqMsg->szOperTime) != 8) return -4;                            // 時間格式異常

    return 0; // 校驗通過
}

關鍵細節:使用 strncpy 替代 strcpy 防止緩衝區溢出;參數傳遞採用指標傳址,避免結構體大量複製開銷。

五、 完整單元測試用例設計

測試策略遵循「正常路徑全覆蓋、異常路徑全攔截」原則:

1. 正常測試用例

  • Case 1:操作類型=1,號碼/時間符合規範 → 預期返回 0,正確列印訊息內容。
  • Case 2:操作類型=2,號碼/時間符合規範 → 預期返回 0,正確列印訊息內容。

操作類型1正常執行

圖3 操作類型為1的正常執行情況

操作類型2正常執行

圖4 操作類型為2的正常執行情況

2. 異常測試用例

  • Case 3:操作類型=3 (非法值) → 預期返回 -2,提示類型錯誤。
  • Case 4:用戶號碼長度=9 (非8位) → 預期返回 -3,提示號碼錯誤。
  • Case 5:操作時間長度=9 (非8位) → 預期返回 -4,提示時間錯誤。

操作類型異常

圖5 操作類型為3的異常執行情況

用戶號碼異常

圖6 用戶號碼為9位的異常執行情況

操作時間異常

圖7 操作時間為9位的異常執行情況

六、 總結與最佳實踐

  1. 協議先行:動碼前先定協議,版本演進靠保留字段,減少破壞性變更。
  2. 防禦性編程:所有指標入參必檢 NULL,邊界條件必加保護(如字串長度截斷)。
  3. 測試左移:單元測試非走過場,要覆蓋正常/邊界/異常三類場景,代碼品質看測試覆蓋率。
  4. 錯誤碼語義化:不同錯誤返回不同負值,便於快速定位問題源頭。

掌握協議設計與單元測試,是從「寫出能跑的代碼」進階為「交付可維護產品」的必經之路。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved