全部例程

使用NetBIOS名称ping W6300

W6300

更新于 2026年10月9日

本篇总结

本例程在 W6300 上实现 NetBIOS 名称解析功能,使 PC 端可直接通过 NetBIOS 名称 ping 设备。

🔑 MH2457、QSPI、UART调试、硬件TOE引擎、NetBIOS、DHCP

硬件平台:本例程基于 W6300-EVB-M4 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板

本示例演示如何在 W6300 上实现 NetBIOS(网络基本输入输出系统)功能,通过名称进行 PING 测试。设备启用 DHCP 后 IP 地址会动态变化,NetBIOS 协议将固定名称映射到动态 IP,PC 端可直接通过名称 ping 设备,无需关心 IP 地址。

前置工具准备

开始本例程前,请确认以下工具已安装:

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 00

NetBIOS 的优势

在实际应用中,设备通常使用 DHCP 方式配置网络地址,IP 地址会动态变化。NetBIOS 协议将固定的名称映射到动态 IP,用户只需记住设备名称即可访问,无需每次查看 IP 地址。W6300 SDK 内置了完整的 NetBIOS 名称服务库(netbios.c/h),名称解码、报文组包、UDP 状态机全部由库函数处理。

硬件连接与拓扑

请注意:

PC 和开发板需接入同一路由器(同一网段),NetBIOS 基于 UDP 广播,广播报文只在同一网段内传播。路由器需开启 DHCP 服务。

  1. Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
  2. 网线连接开发板 RJ45 网口 到路由器 LAN 口
  3. 确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
┌─────────────────────────────────┐
│ 路由器 │
│ 192.168.1.1 │
└────┬──────────────────┬──────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ PC │ │ W6300 │
│CMD:ping │ │ NBNS:137 │
└────┬──────┘ └────┬──────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │─────→ WIZ UartTool
│ MCU │
└───────────┘
网络拓扑:PC 通过 CMD ping NetBIOS 名称,路由器转发广播,W6300 匹配名称后回复 IP,MH2457 通过 QSPI 驱动 W6300

工程结构

工程核心文件如下:

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 地址。

WIZ UartTool V1.0 显示  — PHY 链路 + DHCP + NetBIOS 名称服务监听
CMD ping WIZNET — 名称解析为 192.168.1.9,4 包全通,0% 丢包

常见问题

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 后设备难以访问的问题,可直接通过名称访问设备

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5

Andy

W5500 技术支持专家