使用NetBIOS名称ping W6300
更新于 2026年10月9日
本篇总结
本例程在 W6300 上实现 NetBIOS 名称解析功能,使 PC 端可直接通过 NetBIOS 名称 ping 设备。
硬件平台:本例程基于 W6300-EVB-M4 开发板运行。
采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板
本示例演示如何在 W6300 上实现 NetBIOS(网络基本输入输出系统)功能,通过名称进行 PING 测试。设备启用 DHCP 后 IP 地址会动态变化,NetBIOS 协议将固定名称映射到动态 IP,PC 端可直接通过名称 ping 设备,无需关心 IP 地址。
前置工具准备
开始本例程前,请确认以下工具已安装:
- WIZ UartTool V1.0:串口调试工具:点击下载
NetBIOS 协议简介
NetBIOS(Network Basic Input/Output System,网络基本输入输出系统)由 IBM 在 1983 年开发,用于局域网通信,在局域网共享、网络管理等场景广泛应用。它为网络资源分配唯一名称(16 个字符),支持可靠的会话服务和快速的无连接数据报服务,计算机通过向名称服务器注册和查询,实现基于名称的通信。NetBIOS 工作在会话层,通过 UDP 137 端口进行名称服务,UDP 138 端口用于数据报服务,TCP 139 端口用于会话服务。
NetBIOS 报文主要字段说明:
| 字段 | 说明 |
|---|---|
| Transaction ID | 事务 ID,用于标识请求与响应的唯一事务,便于匹配查询和应答报文 |
| Flags | 标志位,指示报文类型(请求/响应),包含广播标志、操作码及控制信息 |
| Questions | 查询数量,表示当前查询的名称数量,通常为 1 |
| Answer RRs | 回答记录数,表示响应中返回的资源记录数 |
| Question Name | 查询名称,经过特殊编码的 NetBIOS 名称,占用 16 字节 |
| Question Type | 查询类型,0x20 表示 NetBIOS 名称查询 |
| Question Class | 查询类,0x01 表示 IN(互联网类查询) |
报文示例:PC 端发送的 NetBIOS 名称查询广播报文,请求解析设备名称。
|报文解析|
NetBIOS Name Service
Transaction ID: 0xa754 (唯一标识此查询,用于匹配请求与响应)
Flags: 0x0110, Opcode: Name query, Recursion desired, Broadcast (表示这是一个广播查询请求)
Questions: 1 (字段说明仅查询一个设备名称)
Answer RRs: 0 (在响应报文中,该字段会显示解析到的记录数)
Authority RRs: 0 (在响应报文中,用于指示哪些服务器可以授权回答该查询)
Additional RRs: 0 (在某些NetBIOS响应中可能用于携带更多解析信息)
|报文原文|
a7 54 01 10 00 01 00 00 00 00 00 00NetBIOS 的优势
在实际应用中,设备通常使用 DHCP 方式配置网络地址,IP 地址会动态变化。NetBIOS 协议将固定的名称映射到动态 IP,用户只需记住设备名称即可访问,无需每次查看 IP 地址。W6300 SDK 内置了完整的 NetBIOS 名称服务库(netbios.c/h),名称解码、报文组包、UDP 状态机全部由库函数处理。
硬件连接与拓扑
请注意:
PC 和开发板需接入同一路由器(同一网段),NetBIOS 基于 UDP 广播,广播报文只在同一网段内传播。路由器需开启 DHCP 服务。
- Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
- 网线连接开发板 RJ45 网口 到路由器 LAN 口
- 确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
│ 路由器 │
│ 192.168.1.1 │
└────┬──────────────────┬──────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ PC │ │ W6300 │
│CMD:ping │ │ NBNS:137 │
└────┬──────┘ └────┬──────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │─────→ WIZ UartTool
│ MCU │
└───────────┘
工程结构
工程核心文件如下:
Project/
├── main.c ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
└── USER/
├── user_main.c ← 网络地址定义 + user_run() 主流程
├── netbios.c ← NetBIOS 名称服务(do_netbios / netbios_run / 报文解析)
├── netbios.h ← NetBIOS 名称/端口/配置定义
├── wiz_platform.c/h ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
└── wiz_interface.c/h ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测、软件定时器
本例程相比 DHCP 章节的核心新增:NetBIOS 名称服务的初始化、UDP socket 状态机运行、名称解码与响应报文构造。
步骤1:主循环调用 do_netbios
文件:USER/user_main.c — 在完成硬件初始化、DHCP 获取网络地址后,在主循环中调用 do_netbios() 函数,持续监听和响应 NetBIOS 名称查询请求。
while (1)
{
do_netbios(SOCKET_ID);
}
do_netbios() 函数需要传入 socket 号作为参数,设备会在该 socket 上监听 UDP 137 端口的 NetBIOS 名称查询报文。首次调用时完成一次性的初始化(设备名 WIZNET、端口 137、TTL 300 秒),之后每次调用只运行状态机。
步骤2:do_netbios 函数实现
文件:USER/netbios.c — do_netbios() 函数首次调用时用默认配置初始化 NetBIOS 服务,之后每次调用 netbios_run() 驱动状态机。状态机处理两类响应:名称查询(NB)和节点状态查询(NBSTAT),并具备 socket 异常恢复能力。
void do_netbios(uint8_t socket_id)
{
static uint8_t initialized = 0U;
static netbios_config_t config;
if (initialized == 0U)
{
config.socket = socket_id;
config.port = 137U;
config.hostname = "WIZNET";
config.name_suffix = 0x00U;
config.ttl_seconds = 300U;
if (netbios_init(&config) != 0)
{
return;
}
initialized = 1U;
}
netbios_run();
}配置说明
hostname 为设备 NetBIOS 名称(示例为 WIZNET),port 为 NetBIOS 名称服务端口(137),ttl_seconds 为名称记录的有效期。PC 端 ping 的名称必须与此处配置的 hostname 一致(不区分大小写)。
步骤3:NetBIOS 报文解析与响应构造
文件:USER/netbios.c — 收到 UDP 报文后,先解析 NetBIOS 查询报文(parse_question()),判断是否为名称查询或节点状态查询,再匹配配置的设备名,最后构造响应报文并发送。
static int process_query(void)
{
netbios_question_t question;
int32_t result;
uint16_t available;
uint16_t response_length = 0U;
uint16_t remote_port = 0U;
uint8_t remote_ip[4] = {0U, 0U, 0U, 0U};
uint8_t address_length = 4U;
bool matches;
available = getSn_RX_RSR(APP_NETBIOS_SOCKET);
if (available == 0U) return 0;
if (available > sizeof(s_netbios_rx_buffer))
available = (uint16_t)sizeof(s_netbios_rx_buffer);
result = recvfrom(APP_NETBIOS_SOCKET,
s_netbios_rx_buffer,
available,
remote_ip,
&remote_port,
&address_length);
if (result == SOCK_BUSY) return 0;
if (result < 0) return -1;
if ((address_length != 4U) || (remote_port == 0U)) return 0;
memset(&question, 0, sizeof(question));
if (!parse_question(s_netbios_rx_buffer, (uint16_t)result, &question))
return 0;
if (question.class_code != NBNS_CLASS_IN) return 0;
matches = name_matches_configured(question.raw_name);
if ((question.type == NBNS_TYPE_NB) && matches)
response_length = build_name_response(s_netbios_rx_buffer, &question);
else if ((question.type == NBNS_TYPE_NBSTAT) &&
(matches || question.is_wildcard))
response_length = build_node_status_response(s_netbios_rx_buffer, &question);
else
return 0;
if (response_length == 0U) return -1;
memcpy(s_netbios_context.remote_ip, remote_ip, sizeof(remote_ip));
s_netbios_context.remote_port = remote_port;
s_netbios_context.tx_length = response_length;
s_netbios_context.tx_tick = wiz_get_tick_ms();
s_netbios_context.tx_pending = true;
return 0;
}
响应构造:名称查询(NBNS_TYPE_NB)返回设备 IP 地址;节点状态查询(NBNS_TYPE_NBSTAT)返回设备名称和 MAC 地址。begin_response() 负责组装响应头部(复制事务 ID、设置响应标志、填充 answer RRs 计数),build_name_response() / build_node_status_response() 分别填充两类响应的具体内容。
| Socket状态 | 执行操作 |
|---|---|
| SOCK_CLOSED | 初始化 UDP socket 并绑定 137 端口,读取本机 IP / MAC |
| SOCK_UDP | 接收查询报文,解析名称,匹配后构造响应并发送 |
| 其他状态 | 状态异常超过 2 秒则关闭 socket 并重开 |
步骤4:名称解码与匹配
文件:USER/netbios.c — NetBIOS 名称在传输时经过一级编码,每个原始字符被编码为两个字符。parse_question() 中直接将编码字节减去 'A' 后按高 4 位 / 低 4 位还原为原始名称。
for (index = 0U; index < NBNS_RAW_NAME_SIZE; ++index)
{
uint8_t high = query[offset++];
uint8_t low = query[offset++];
if ((high < (uint8_t)'A') || (high > (uint8_t)'P') ||
(low < (uint8_t)'A') || (low > (uint8_t)'P'))
{
return false;
}
question->raw_name[index] =
(uint8_t)(((high - (uint8_t)'A') << 4U) |
(low - (uint8_t)'A'));
}
解码原理:每个原始字符被拆成两个编码字符,第一个编码字符减去 'A' 后左移 4 位作为高 4 位,第二个编码字符减去 'A' 后作为低 4 位,或运算后组合成一个字节即为原始字符。name_matches_configured() 将解码后的名称与配置的 hostname 比对(不区分大小写),匹配才回复响应。
运行验证
烧录例程运行后,首先进行 PHY 链路检测,然后通过 DHCP 获取网络地址并打印,最后程序开始持续接收和响应 NetBIOS 请求。打开 WIZ UartTool V1.0,连接对应 COM 口(115200 / 8N1),预期串口输出如下:
MH2457 W6300 QSPI example start
W6300 NETBIOS example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
DHCP running
DHCP success!
====================================================================================================
W6300 network configuration : DHCP
MAC : 00:08:DC:72:30:12
IP : 192.168.1.9
Subnet Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
====================================================================================================
please try ping WIZNET
请注意
测试实例需要 PC 端和 W6300 处于同一网段。在 PC 端打开 CMD,使用 ping WIZNET 即可通过名称访问设备,无需关心设备的 IP 地址。


常见问题
Q: NetBIOS 使用什么端口和协议
NetBIOS 名称服务使用 UDP 137 端口,数据报服务使用 UDP 138 端口,会话服务使用 TCP 139 端口。本例程中 W6300 主要使用 UDP 137 端口来监听和响应 NetBIOS 名称查询请求。
Q: 为什么 PC 端可以直接通过名称 ping 设备
当 PC 端 ping 一个 NetBIOS 名称时,会先查询本地缓存,若无记录则发出 NetBIOS 广播请求。W6300 收到请求后检查名称是否匹配,若匹配则回复自身 IP 地址。PC 端建立名称与 IP 的映射后,即可将名称替换为 IP 进行 ping 操作。
Q: NetBIOS 名称有什么限制
NetBIOS 名称长度为 16 个字符,在网络中作为节点的唯一标识。名称经过特殊编码(一级编码)后传输,每个字符被编码为两个字符。配置的设备名不能超过 15 个字符,剩余 1 字节用于名称后缀(本例程为 0x00)。
Q: 设备不在同一网段能否使用 NetBIOS
NetBIOS 名称查询基于 UDP 广播,广播报文通常只在同一网段内传播。因此 PC 端和 W6300 需要处于同一网段才能正常进行 NetBIOS 名称解析。若跨网段使用,需要通过网络中的 NBNS(NetBIOS Name Server)来转发查询请求。
Q: 如何修改设备的 NetBIOS 名称
修改 do_netbios() 中初始化配置的 config.hostname 字段即可(当前为 "WIZNET")。名称不区分大小写,长度不超过 15 个字符。PC 端 ping 时使用相同的名称即可解析。修改后需重新烧录运行。
总结
- 协议定位:NetBIOS 是 IBM 开发的局域网名称解析协议,通过 UDP 137 端口工作,实现基于名称的通信
- 核心功能:为网络节点分配唯一 16 字符名称,支持动态注册与解析
- 工作流程:PC 查询缓存 → 广播请求 → 设备匹配名称并回复 IP → PC 建立映射 → ping 操作
- 实现方式:do_netbios() 首次调用完成初始化,之后由 netbios_run() 驱动状态机;parse_question() 解析编码名称,build_name_response() / build_node_status_response() 构造响应
- 应用价值:解决 DHCP 动态分配 IP 后设备难以访问的问题,可直接通过名称访问设备