NetBIOS协议演示


关键词:NetBIOS  W5500  WIZnet  W5500EVB  局域网


NetBIOS协议是一种在局域网上的程序可以使用的应用程序编程接口(API),为程序提供了请求低级服务的统一的命令集,作用是为了给局域网提供网络以及其他特殊功能,几乎所有的局域网都是在NetBIOS协议的基础上工作的。 NetBIOS协议,简单来说就是通过访问设备名称就可以实现对IP地址的访问。在Windows操作系统中,默认情况下在安装TCP/IP协议后会自动安装NetBIOS协议。NetBIOS的报文类型较多、结构复杂,在不同的网络环境和不同的用途中会使用不同的报文,可用端口进行区分, NetBIOS数据报报文使用UDP 138端口,NetBIOS会话报文使用TCP 139端口。本节主要通过NetBIOS协议实现把IP地址解析为对应的一个名字,就比如180.97.33.107是百度服务器的IP地址,对应的名字是“www.baidu.com”。这样我们就不用记住很多的IP地址,通过一个简单的名字就可搜索到相应的信息。 本例程首先通过DHCP获取一个动态IP地址分配给W5500,然后通过NetBIOS协议来解析W5500这个名字和IP地址对应,然后添加HTTP服务器功能,在网页中输入W5500就可以进入相应的网页信息,在windows下ping W5500也可以得到对应的IP地址信息。程序的Main很简单,主要是网络初始化和芯片的初始化。 由于本程序通过DHCP获取动态IP以后,再通过NetBIOS实现名字解析的,所以要在w5500_conf.c文件下定义ip_from为IP_FROM_DHCP。NetBIOS的处理主要在NetBIOS.c中。在do_netbios函数中对UDP广播查询做了解析,并且回应。这就完成了b节点的NetBIOS名称服务。在do_netbios中一个Socket在指定的 端口一直侦听,如果收到数据包就判断格式,看是不是NetBIOS查询包。如果是,调用netbios_name_decoding函数解包。之后按照NetBIOS格式组包回复。

NetBIOS实现过程示意图如下:

主循环代码如下:
while(1)								/*循环执行的函数*/ 
{
	do_dhcp();                        	/*从DHCP服务器获取IP地址*/
	if(dhcp_ok==1)						/*获取IP地址之后*/
	{
		do_https();                    	/*打开HTTP Server*/
		do_netbios();                   /*NetBios测试程序*/
	} 
}

void do_netbios(void)
{
	unsigned char state;
  	unsigned int len,i;
  	state = getSn_SR(NETBIOS_SOCK);
  	switch(state)
  	{
		case SOCK_UDP:
			if((len=getSn_RX_RSR(NETBIOS_SOCK))>0)
			{
				unsigned char rem_ip_addr[4];
				uint16 rem_udp_port;
				char netbios_name[NETBIOS_NAME_LEN+1];
				NETBIOS_HDR* netbios_hdr;
				NETBIOS_NAME_HDR* netbios_name_hdr;
				if (((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");	
					netbios_name_decoding( (char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
					printf("name is %s\r\n",netbios_name);			
					if (strcmp(netbios_name, NETBIOS_W5500_NAME) == 0) 
					{
						uint8 ip_addr[4];	
						NETBIOS_RESP *resp = (NETBIOS_RESP*)netbios_tx_buf;
						printf("name is matched!\r\n");
				/* 处理NetBIOS响应包的header*/
						resp->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;
						memcpy( 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);						
						sendto(NETBIOS_SOCK, (unsigned char*)resp, sizeof(NETBIOS_RESP), rem_ip_addr, rem_udp_port);
						printf("send response\r\n");
			   		}
					else 
					printf("name is not matched!\r\n");
				}
			}
		break;		
		case SOCK_CLOSED:
		close(NETBIOS_SOCK);
		socket(NETBIOS_SOCK,Sn_MR_UDP,NETBIOS_PORT,0);
		break;
		default:
		break;
  	 }
}
NetBIOS的具体测试步骤如下
  1. 本例程通过DHCP动态获取IP信息来配置W5500的IP信息,所以在w5500_conf.c文件中设置ip_from为IP_FROM_DHCP。
  2. 对代码进行编译,之后将程序烧录到野火开发板。
  3. 连接好网线,USB串口线。打开串口调试工具,复位野火开发板,从输出结果可以得到图1设置信息。
  4. 在Windows下的具体操作是,开始→运行→(键入)cmd,输入 ping W5500→回车。看到回复信息如图2所示。W5500对应的IP地址就是192.168.1.109,说明NetBIOS名称解析成功。
  5. 在IE浏览器中输入W5500并点击回车,看到网页信息如图3所示。W5500对应的信息也在网页中正确显示,说明NetBIOS名称解析成功。

图1:NetBIOS串口打印信息


图2:ping W5500回复信息


图3:网页登陆信息

例程下载:【NetBIOS】
编译环境:keil V5.11
硬件要求:W5500EVB