什麼是 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 數 |
| 0x34 | NetBIOS 環境未定義 |
| 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 位元通用。
現代替代方案
| 需求 | 建議技術 |
| 取得 MAC 位址 | GetAdaptersAddresses() (IPHLPAPI)、GetIfTable2() |
| 區域網路名稱解析 | DNS、mDNS (Bonjour)、LLMNR |
| 簡易訊息傳遞 | UDP Broadcast、ZeroMQ、gRPC、Named Pipe |
| 可靠連線通訊 | TCP (Winsock)、WebSocket、Named Pipe |
| 舊系統整合 | NetBIOS (維持現狀) |
結語
NetBIOS 是網路程式設計的歷史遺產,理解其 NCB 架構、同步/非同步模式、名稱管理、工作階段與資料報差異,有助於維護舊系統。新專案強烈建議採用標準 TCP/IP Socket 或更高層級框架,獲得跨平台、可擴展、安全的通訊能力。
- 上一篇文章: C++ 核心筆記 (一):類別與物件基礎完整指南
- 下一篇文章: C++Builder 5 ADO 資料庫程式設計:從元件架構到 Master/Detail 實作
Copyright ©
程式碼之家 All Rights Reserved