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

C++Builder NetBIOS 程式設計:從基礎到實作範例

     編輯:關於C++

什麼是 NetBIOS?

NetBIOS (Network Basic Input/Output System) 是 IBM 於 1984 年為 PC Network 定義的 API,提供工作階層 (Session Layer) 的網路通訊介面。雖然古老,但在區域網路 (LAN) 環境下仍廣泛用於舊系統相容、簡易訊息傳遞、名稱解析。Windows 內建 Netbios() 函數 (在 nb30.h/netbios.h) 供應用程式呼叫。

核心概念

概念說明
NCB (Network Control Block)64 位元組控制區塊,傳遞命令碼、緩衝區、長度、名稱、埠號、回呼等參數。呼叫前必須 memset(&ncb, 0, sizeof(ncb)) 清零。
名稱 (Name)16 位元組識別碼,用於識別工作站/群組。Add Name 註冊,Delete Name 註銷。
工作階段可靠、雙向、連線導向通訊 (Call/Listen/Send/Receive/Hang Up)。
資料報不可靠、無連線、單向傳遞。廣播 (Send Broadcast Datagram/Receive Broadcast Datagram) 與 定向 (Send Datagram/Receive Datagram) 兩種。
LANA 數邏輯介面卡編號 (0, 1, 2...),對應實體網卡/協議綁定。ncb_lana_num 指定命令作用介面。
同步 vs 非同步命令碼高位元 = 0:同步 (阻塞直到完成);= 1:非同步 (立即返回,完成時呼叫 ncb_post 回呼或置事件 ncb_event)。

常用命令碼


NCBRESET       (0x32)  重設介面卡,清除名稱表、斷開所有工作階段
NCBASTAT       (0x33)  取得介面卡狀態 (MAC 位址、名稱表、錯誤計數)
NCBADDNAME     (0x30)  註冊本地名稱
NCBDELNAME     (0x31)  刪除本地名稱
NCBCALL        (0x10)  發起工作階段連線
NCBLISTEN      (0x11)  側聽工作階段請求
NCBSEND        (0x14)  工作階段傳送資料
NCBRECV        (0x15)  工作階段接收資料
NCBHANGUP      (0x12)  關閉工作階段
NCBSENDDG      (0x20)  發送定向資料報
NCBRECVDG      (0x21)  接收定向資料報
NCBSENDBC      (0x22)  發送廣播資料報
NCBRECVBC      (0x23)  接收廣播資料報

NCB 結構關鍵欄位


typedef struct _NCB {
    UCHAR  ncb_command;      // 命令碼 (高位元=1 表非同步)
    UCHAR  ncb_retcode;      // 返回碼 (0=成功,其他見下表)
    UCHAR  ncb_lsn;          // 本地工作階段號 (由系統指派)
    UCHAR  ncb_num;          // 名稱號碼 (Add Name 後取得)
    PUCHAR ncb_buffer;       // 資料緩衝區指標
    WORD   ncb_length;       // 緩衝區長度
    UCHAR  ncb_callname[16]; // 遠端名稱 (Call/SendDG 目標)
    UCHAR  ncb_name[16];     // 本地名稱
    UCHAR  ncb_rto;          // 接收逾時 (單位: 500ms)
    UCHAR  ncb_sto;          // 發送逾時 (單位: 500ms)
    void  (*ncb_post)(struct _NCB*); // 非同步完成回呼
    UCHAR  ncb_lana_num;     // LANA 號
    UCHAR  ncb_cmd_cplt;     // 命令完成碼 (0xFF=進行中)
    UCHAR  ncb_reserve[10];  // 保留
    HANDLE ncb_event;        // 非同步事件控制代碼
} NCB;

常見返回碼

碼意義
0x00成功
0x03無效命令碼
0x05命令逾時
0x0D名稱重複
0x0E名稱表滿
0x14找不到遠端名稱/無回應
0x15名稱無效/已刪除
0x19名稱衝突
0x21介面忙碌
0x23無效 LANA 數
0x34NetBIOS 環境未定義
0x35系統資源耗盡
0xFF命令執行中 (非同步)

完整範例:取得本機 MAC 位址與名稱表 (NCBASTAT)


// NetBIOS_MAC.cpp - C++Builder Console App
#pragma hdrstop
#include <windows.h>
#include <nb30.h>        // NetBIOS 定義
#include <stdio.h>
#include <conio.h>

// 適配器狀態緩衝區 (NCBASTAT 回傳)
typedef struct _ASTAT {
    ADAPTER_STATUS adapt;
    NAME_BUFFER    NameBuff[30];
} ASTAT, *PASTAT;

bool ResetAdapter(UCHAR lana) {
    NCB ncb = {0};
    ncb.ncb_command = NCBRESET;
    ncb.ncb_lana_num = lana;
    return Netbios(&ncb) == NRC_GOODRET;
}

int main() {
    UCHAR lana = 0; // 通常 0 為第一張網卡
    if (!ResetAdapter(lana)) {
        printf("重設介面卡失敗\\n");
        getch(); return 1;
    }

    NCB ncb = {0};
    ncb.ncb_command  = NCBASTAT;
    ncb.ncb_lana_num = lana;
    ncb.ncb_callname[0] = '*'; // '*' 表示查詢本機
    for (int i = 1; i < 16; ++i) ncb.ncb_callname[i] = ' ';

    ASTAT Adapter = {0};
    ncb.ncb_buffer = (PUCHAR)&Adapter;
    ncb.ncb_length = sizeof(Adapter);

    UCHAR ret = Netbios(&ncb);
    printf("NCBASTAT 返回碼: 0x%02X\\n", ret);

    if (ret == NRC_GOODRET) {
        // MAC 位址
        printf("MAC 位址: ");
        for (int i = 0; i < 6; ++i) {
            printf("%02X%c", Adapter.adapt.adapter_address[i], (i==5?'\n':'-'));
        }
        // 介面卡類型
        if (Adapter.adapt.adapter_type == 0xFF) printf("Token Ring\\n");
        else if (Adapter.adapt.adapter_type == 0xFE) printf("Ethernet\\n");
        else printf("其他 (0x%02X)\\n", Adapter.adapt.adapter_type);

        // 軟體版本
        printf("軟體版本: %d.%d\\n", Adapter.adapt.rev_major, Adapter.adapt.rev_minor);
        // 本地名稱表
        printf("本地名稱數: %d\\n", Adapter.adapt.name_count);
        for (int i = 0; i < Adapter.adapt.name_count; ++i) {
            char name[17] = {0};
            memcpy(name, Adapter.NameBuff[i].name, 16);
            printf("  [%02d] %s (num=%d, flags=0x%02X)\\n",
                   i, name, Adapter.NameBuff[i].name_num, Adapter.NameBuff[i].name_flags);
        }
    }
    getch();
    return 0;
}

編譯與執行注意事項

  • 專案需連結 netapi32.lib (隱含由 nb30.h 引入)。
  • Windows 10/11 預設停用 NetBIOS over TCP/IP,需在網卡屬性 → IPv4 進階 → WINS → 啟用「NetBIOS over TCP/IP」或透過登錄 HKLM\SYSTEM\CurrentControlSet\Services\NetBT\Parameters\Interfaces\Tcpip_{GUID} 設定 NetbiosOptions=1。
  • 需系統管理員權限 執行 (存取裝置驅動)。
  • 64 位元應用程式同樣適用,Netbios() 為 32/64 位元通用。

現代替代方案

結語

NetBIOS 是網路程式設計的歷史遺產,理解其 NCB 架構、同步/非同步模式、名稱管理、工作階段與資料報差異,有助於維護舊系統。新專案強烈建議採用標準 TCP/IP Socket 或更高層級框架,獲得跨平台、可擴展、安全的通訊能力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求建議技術
取得 MAC 位址GetAdaptersAddresses() (IPHLPAPI)、GetIfTable2()
區域網路名稱解析DNS、mDNS (Bonjour)、LLMNR
簡易訊息傳遞UDP Broadcast、ZeroMQ、gRPC、Named Pipe
可靠連線通訊TCP (Winsock)、WebSocket、Named Pipe
舊系統整合NetBIOS (維持現狀)