当前位置: 首页 > news >正文

【第十二章 W55MH32 NetBIOS示例标题】

目录

1 NetBIOS简介

2 NetBIOS特点

3 NetBIOS应用场景

4 NetBIOS的基本工作流程

5 NetBIOS报文解析

6 实现过程

7 运行结果

8 总结


本篇文章我们将详细介绍如何在W55MH32芯片上面实现NetBIOS功能,并通过实战例程,为大家讲解如何通过名称进行PING测试。

该例程用到的其他网络协议,例如DHCP请参考相关章节。有关W55MH32的初始化过程,请参考Network Install 章节,这里将不再赘述。

1 NetBIOS简介

NetBIOS(Network Basic Input/Output System,网络基本输入输出系统)主要用于数十台计算机的小型局域网资源共享。NetBIOS是一种应用程序编程接口(API),应用于局域网程序中,为程序提供请求低级服务的统一的命令集,作用是给局域网提供网络服务以及其他特殊功能。自诞生起,NetBIOS 成为许多其他网络应用程序的基础。很多局域网都是在 NetBIOS 的基础上工作的。在 NetBIOS 局域网环境下,计算机通过名字被系统识别。网络中每台计算机都有用不同方法编的永久性名称。NetBIOS名称用来在网络上鉴别资源。程序可以用这些名称开始和结束会话。每个程序都有独特的NetBIOS名称。每台支持应用的网络设备也有用户定义或通过内部方法获得的 NetBIOS站名。NetBIOS 名称能包含至多16位阿拉伯数字。在整个资源路由网络里,字符组合是唯一的。在一台使用 NetBIOS 的网络设备在网络上能完全工作起来之前,网络设备必须先登记 NetBIOS名称。

2 NetBIOS特点

  1. 唯一命名规则:NetBIOS为网络中的每个节点分配一个唯一的名称,长度为16个字符。这一名称在网络中作为节点的标识,方便用户和应用程序识别和访问特定的资源。
  2. 动态注册与解析:节点在接入网络时,会动态地将其NetBIOS名称注册到网络中。当一个节点需要与另一个节点通信时,它会通过名称解析机制将NetBIOS名称转换为对应的以太网地址(MAC地址)。这种动态的注册和解析过程使得网络配置更加灵活,节点可以随时加入或离开网络,而无需复杂的手动配置。
  3. 面向连接(TCP)和无连接(UDP)通信均支持:它支持广播和组播,支持三个分开的服务:名字、会话和数据报。
  4. 较好的兼容性好该协议具有较好的兼容性,能够与其他网络协议(如TCP/IP)共存。在现代网络环境中,虽然TCP/IP协议占据主导地位,但NetBIOS仍然可以在某些特定的应用场景中发挥作用,并且可以与基于TCP/IP的应用程序进行交互。

3 NetBIOS应用场景

W55MH32使用NetBIOS 可以进行以下几种应用:

  1. 设备名称解析:在嵌入式系统中,许多设备(如物联网设备、智能家居设备等)可能没有配置复杂的DNS系统。通过NetBIOS名称服务,设备可以使用简单的名称而不是复杂的IP地址进行通信。
  2. 网络浏览服务:通过NetBIOS广播或点对点查询,嵌入式设备能够在网络资源管理器中显示自身信息,使用户能够快速访问设备。

4 NetBIOS的基本工作流程

NetBIOS主要提供以下三种服务:

NetBIOS名称服务(Name Service):负责NetBIOS名称注册和解析(对应NBNS)。

NetBIOS数据报服务(Datagram Service):支持无连接的通信(UDP)。

NetBIOS会话服务(SessionService):支持面向连接的通信(TCP)。

NBNS是NetBIOS的一部分,专门负责实现NetBIOS名称服务(Name Service)的功能。它的作用是将NetBIOS名称解析为对应的IP地址。

PC端ping NetBIOS名称的基本工作流程如下:

第一步:当PC端PING的是一个NetBIOS 名称时,首先会查询自身的 NetBIOS 远程缓存名称表中是否存在记录,存在则将NetBIOS名称替代为IP地址,不存在则PC 端发出 NetBIOS 广播请求。

第二步:当设备端接收到NetBIOS请求后,会检查该请求中的名称是否与自身的名称相符。若相符,设备端会向请求端回复自身的IP地址。

第三步:PC端在收到设备端的响应后,会将该响应中包含的 IP 地址和NetBIOS名称建立映射关系存储到 NetBIOS 远程缓存名称表中。

第四步:PC端根据NetBIOS 远程缓存名称表中的映射关系,将NetBIOS名称替换成IP进行PING操作。

5 NetBIOS报文解析

NetBIOS(Network Basic Input/Output System)报文用于局域网内计算机的设备发现与名称解析。它工作在会话层,通过UDP 137端口进行名称服务,用于主机名与IP地址的映射;UDP 138端口用于数据报服务,支持无连接消息传输;TCP 139端口用于会话服务,支持面向连接的通信。

NetBIOS报文格式如下:

字节偏移

字段名称

长度 (字节)

描述

0

Transaction ID

2

事务 ID,用于匹配请求和响应

2

Flags

2

标志位,表示报文类型和属。

4

Questions

2

查询的名称数量

6

Answer RRs

2

回答记录数,表示响应的记录数量

8

Authority RRs

2

授权记录数

10

Additional RRs

2

额外记录数

12

Question Name

可变长度

查询的 NetBIOS 名称,16 字节编码

可变

Question Type

2

查询类型(如 0x20 表示名称查询)

可变+2

Question Class

2

查询类(如 IN = 0x01 表示互联网类)

字段解释

1.Transaction ID (事务 ID):

用于标识请求与响应的唯一事务 ID,便于匹配查询和应答报文。

2.Flags (标志位):

指示报文类型(请求/响应)。

包含广播标志、操作码及其他控制信息。

3.Questions (查询数量):

表示当前查询的名称数量,通常为 1。

4.Answer RRs (回答记录数):

表示响应中返回的资源记录数。

5.Authority RRs (授权记录数):

表示提供的授权名称服务器记录数。

6.Additional RRs (额外记录数):

提供额外的附加信息,如 IP 地址或其他补充数据。

7.Question Name (查询名称):

查询的 NetBIOS 名称,经过特殊编码,占用 16 字节,末尾以 0x00 结束。

8.Question Type (查询类型):

指定查询的类型,如 0x20 表示 NetBIOS 名称查询。

9.Question Class (查询类):

指定查询的类,0x01 表示 IN(互联网类查询)。

报文示例

|报文解析|

NetBIOS Name Service

    Transaction ID: 0xa753    (唯一标识此查询,用于匹配请求与响应)

    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

6 实现过程

接下来,我们看看如何在W55MH32上实现NetBIOS功能。

注意:测试实例需要PC端和W55MH32处于同一网段。

在主循环调用do_netbios()函数,如下所示:

while (1)
{do_netbios(SOCKET_ID);
}

do_netbios()函数需要传入一个参数,该参数是socket号,do_netbios()函数如下:

void do_netbios(uint8_t sn)
{unsigned char state;unsigned int  len;state = getSn_SR(sn);switch (state){case SOCK_UDP:if ((len = getSn_RX_RSR(sn)) > 0){unsigned char     rem_ip_addr[4];uint16_t          rem_udp_port;char              netbios_name[NETBIOS_NAME_LEN + 1];NETBIOS_HDR      *netbios_hdr;NETBIOS_NAME_HDR *netbios_name_hdr;len = recvfrom(sn, (unsigned char *)&netbios_rx_buf, len, rem_ip_addr, &rem_udp_port);printf("rem_ip_addr=%d.%d.%d.%d:%d\r\n", rem_ip_addr[0], rem_ip_addr[1], rem_ip_addr[2], rem_ip_addr[3], rem_udp_port);netbios_hdr      = (NETBIOS_HDR *)netbios_rx_buf;netbios_name_hdr = (NETBIOS_NAME_HDR *)(netbios_hdr + 1);// If the packet is a NetBIOS query packetif (((netbios_hdr->flags & ntohs(NETB_HFLAG_OPCODE)) == ntohs(NETB_HFLAG_OPCODE_NAME_QUERY)) && ((netbios_hdr->flags & ntohs(NETB_HFLAG_RESPONSE)) == 0) && (netbios_hdr->questions == ntohs(1))){printf("netbios name query question\r\n");// Decode the NetBIOS packagenetbios_name_decoding((char *)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));printf("name is %s\r\n", netbios_name);// If the query is made against the native Netbiosif (strcmp(netbios_name, NETBIOS_W5500_NAME) == 0){uint8_t       ip_addr[4];NETBIOS_RESP *resp = (NETBIOS_RESP *)netbios_tx_buf;// Handle the header of the NetBIOS response packetresp->resp_hdr.trans_id      = netbios_hdr->trans_id;resp->resp_hdr.flags         = htons(NETB_HFLAG_RESPONSE | NETB_HFLAG_OPCODE_NAME_QUERY | NETB_HFLAG_AUTHORATIVE | NETB_HFLAG_RECURS_DESIRED);resp->resp_hdr.questions     = 0;resp->resp_hdr.answerRRs     = htons(1);resp->resp_hdr.authorityRRs  = 0;resp->resp_hdr.additionalRRs = 0;// Process the header data of the NetBIOS response packetmemcpy(resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));resp->resp_name.nametype = netbios_name_hdr->nametype;resp->resp_name.type     = netbios_name_hdr->type;resp->resp_name.cls      = netbios_name_hdr->cls;resp->resp_name.ttl      = htonl(NETBIOS_NAME_TTL);resp->resp_name.datalen  = htons(sizeof(resp->resp_name.flags) + sizeof(resp->resp_name.addr));resp->resp_name.flags    = htons(NETB_NFLAG_NODETYPE_BNODE);getSIPR(ip_addr);memcpy(resp->resp_name.addr, ip_addr, 4);// Send a response packetsendto(sn, (unsigned char *)resp, sizeof(NETBIOS_RESP), rem_ip_addr, rem_udp_port);printf("send response\r\n");}}}break;case SOCK_CLOSED:close(sn);socket(sn, Sn_MR_UDP, NETBIOS_PORT, 0);break;default:break;}
}

进入do_netbios()函数会执行一个UDP协议的状态机,当收到消息后,首先会判断是否为NetBIOS报文,如果为NetBIOS报文则会进入netbios_name_decoding()函数解析NetBIOS名称,当名称与W55MH32的NetBIOS名称一致时,则返回响应报文。

netbios_name_decoding()函数如下:

static int netbios_name_decoding(char *name_enc, char *name_dec, int name_dec_len)
{char *pname;char  cname;char  cnbname;int   index = 0;// Decode the name of the former NetBIOSpname = name_enc;for (;;){/* Every two characters of the first level-encoded name* turn into one character in the decoded name. */cname = *pname;if (cname == '\0')break; // no more charactersif (cname == '.')break; // scope ID followsif (cname < 'A' || cname > 'Z'){// Not legal.return -1;}cname   -= 'A';cnbname  = cname << 4;pname++;cname = *pname;if (cname == '\0' || cname == '.'){/* No more characters in the name - but we're in* the middle of a pair.  Not legal. */return -1;}if (cname < 'A' || cname > 'Z'){// Not legal.return -1;}cname   -= 'A';cnbname |= cname;pname++;// Do we have room to store the character?if (index < NETBIOS_NAME_LEN){// Yes - store the character.name_dec[index++] = (cnbname != ' ' ? cnbname : '\0');}}return 0;
}

7 运行结果

烧录例程运行后,首先进行了PHY链路检测,然后是通过DHCP获取网络地址并打印网络地址信息,最后程序开始持续接收和响应 NetBIOS 请求。如下图所示:

8 总结

本文讲解了如何在 W55MH32 芯片上实现 NetBIOS 功能,通过实战例程展示了利用 NetBIOS 进行名称 PING 测试的具体过程,包括 NetBIOS 功能的调用、请求处理、名称解析和响应发送等关键步骤。文章详细介绍了 NetBIOS 的概念、特点、应用场景、基本工作流程和报文解析,帮助读者理解其在小型局域网资源共享和设备通信中的重要作用。

下一篇文章将聚焦 UPnP,解析其核心原理及在网络设备互联互通中的应用,同时讲解如何在相关设备上实现 UPnP 功能,敬请期待!

http://www.dtcms.com/a/294798.html

相关文章:

  • ChatGPT桌面版深度解析
  • clientHeight(用于获取元素的可视高度)
  • 大致自定义文件I/O库函数的实现详解(了解即可)
  • 计算机网络学习----域名解析
  • uni-app平板端自定义样式合集
  • 【67】MFC入门到精通——MFC 销售管理系统 项目实现详细教程
  • 【自动化运维神器Ansible】深入解析Ansible Host-Pattern:精准控制目标主机的艺术
  • PowerShell自动化核对AD与HR系统账户信息实战指南
  • Hexo - 免费搭建个人博客02 - 创建个人博客
  • 智能办公如何创建e9流程
  • 力扣刷题(第九十六天)
  • Windows 用 Python3 快速搭建 HTTP 服务器
  • Google Chrome V8< 14.0.221 类型混淆漏洞
  • 基于Kafka实现动态监听topic功能
  • 元图CAD:高效分割图纸的智能解决方案
  • CSP-J系列【2024】P11230 [CSP-J 2024] 接龙题解
  • 数据持久化--PlayerPrefs
  • GRE实验
  • ROS是什么?
  • 力扣面试150(39/150)
  • PyTorch中的词嵌入层(nn.Embedding)详解与实践指南
  • js生成器
  • 【黑产大数据】2025年上半年互联网黑灰产趋势年度总结
  • MySQL 8.0 OCP 1Z0-908 题目解析(33)
  • 【硬件】Fan in和Fan out
  • 《地牢探险者:深渊回响》(C++游戏,爆肝7.8个小时,全文14591字)(求一个免费的三连)
  • c# sqlsuger 获取关联表中一个值
  • SET: Spectral Enhancement for Tiny Object Detection(CVPR2025)
  • iOS WebView 远程调试实战 解决表单输入被键盘遮挡和焦点丢失问题
  • VRRP技术-设备备份技术