Windows网络编程实用教程:第7章 NetBIOS网络编程技术_第1页
Windows网络编程实用教程:第7章 NetBIOS网络编程技术_第2页
Windows网络编程实用教程:第7章 NetBIOS网络编程技术_第3页
Windows网络编程实用教程:第7章 NetBIOS网络编程技术_第4页
Windows网络编程实用教程:第7章 NetBIOS网络编程技术_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第7章 NetBIOS网络编程技术课程描述NetBIOS(NETwork Basic Input/Output System,网络基本输入/输出系统)定义了一种软件接口以及在应用程序和连接介质之间提供通信接口的标准方法。它可以提供名字服务、会话服务和数据库服务,基于NetBIOS的比较典型的应用是获取远程计算机的Mac地址、名称和所在工作组等信息。本章将对NetBIOS网络编程技术进行介绍。本章知识点7.1 NetBIOS协议及应用7.2 NetBIOS开发接口7.3 在程序中实现NBTSTAT命令的功能7.1 NetBIOS协议及应用7.1.1 NetBIOS协议7.1.2 使用NBTSTA

2、T命令7.1.1 NetBIOS协议NetBIOS协议最初由IBM开发,微软公司在此基础上对该协议进行了完善,并在Windows上提供了对NetBIOS协议的支持。网络邻居功能就是基于NetBIOS协议的。在Windows中安装TCP/IP协议的同时就会安装NetBIOS协议。下面介绍一下在Windows 2003中启用和配置NetBIOS协议的方法。 配置NetBIOS右键单击桌面上的网络邻居图标,在弹出菜单中选择“属性”,打开“网络连接”窗口。右键单击“本地连接”图标,在弹出菜单中选择“属性”,打开“本地连接属性”对话框。 配置NetBIOS选中“Internet协议(TCP/IP)”项,

3、单击“属性”按钮,打开“Internet协议(TCP/IP)”属性对话框。单击“高级”按钮,打开“高级TCP/IP设置”对话框。单击“WINS”选项卡,可以对NetBIOS协议进行设置。1LANA编号LANA(LAN Adapter,LAN适配器)编号是NetBIOS进行网络编程的关键,它对应于网卡及传输协议的唯一组合。例如,假定某个工作站安装了两块网卡,以及两种具有NetBIOS能力的传输协议(例如TCP/IP和NetBEUI),那么将共有下面4个LANA编号:表示“TCP/IP网卡1”对。表示“NetBEUI网卡1”对。表示“TCP/IP网卡2”对。表示“NetBEUI网卡2”对。2名字服

4、务NetBIOS协议支持建立名字服务器,负责查找目标主机对应的IP地址,并赋予一个NetBIOS名称。名字服务提供的主要功能如下:添加名字,即注册一个NetBIOS名字。添加组名,即注册一个NetBIOS组名。删除名字,即取消一个NetBIOS名字和组名的注册。查询名字,即在网络中搜索NetBIOS名字。3会话服务会话服务提供的主要功能如下:调用,即打开一个到远程NetBIOS名字的会话。侦听,即侦听其他程序的连接请求。挂起,即关闭一个会话。发送,即向会话对端的计算机发送一个数据包,并等待对方确认。无确认发送,即向会话对端的计算机发送一个数据包,但不需要对方确认。接收,即等待从会话对端发送的数

5、据包到达。4数据报服务数据报服务提供的主要功能如下:发送数据报,即向远程NetBIOS名字发送一个数据报。发送广播数据报,即向网络中所有NetBIOS名字发送数据报。接收数据报,即等待从发送数据报操作中到达的数据。接收广播数据报,即等待从发送广播数据报操作中到达的数据。在Windows中,如果安装了NetBIOS协议,则系统将自动开放下列端口:137端口,主要作用是在局域网中提供计算机的名称或IP地址查询服务。138端口,主要作用是提供NetBIOS环境下的计算机名浏览功能。139端口,主要作用是提供文件和打印机共享的功能。7.1.2 使用NBTSTAT命令在Windows命令窗口中执行NBT

6、STAT命令,可以获取指定远程计算机的基本信息,包括Mac地址、计算机名和所属工作组等。NBTSTAT命令的格式如下:NBTSTAT -a RemoteName -A IP address -c -n -r -R -RR -s -S interval NBTSTAT参数的具体说明参 数说 明-a RemoteName列出指定名称的远程机器的名称表,RemoteName表示指定的远程主机计算机名-A IP address列出指定 IP 地址的远程机器的名称表,IP address表示用点分法表示的IP地址-c列出远程计算机名称及其IP地址的 NBT 缓存-n列出本地的NetBIOS名称-r列出通

7、过广播和经由WINS解析的名称-R清除和重新加载远程缓存名称表-RR将名称释放包发送到WINS,然后启动刷新-s列出将目标IP地址转换成计算机NetBIOS名称的会话表-S列出具有目标IP地址的会话表interval重新显示选定的统计、每次显示之间暂停的间隔秒数。按Ctrl+C停止重新显示统计实例NBTSTAT -A 68NBTSTAT -a LEE-THINKPAD7.2 NetBIOS开发接口7.2.1 NetBIOS操作7.2.2 NCB结构体7.2.3 其他常用NetBIOS结构体7.2.4 Netbios()函数7.2.5 获取LANA上的所有NetBIOS名字

8、7.2.6 获取网络适配器上的MAC地址7.2.1 NetBIOS操作协议驱动程序对外公布NetBIOS接口,并将NetBIOS命令映射到协议驱动程序的内部命令。NetBIOS模拟器接收NetBIOS命令,将它们转换成TDI(Transport Driver Interface,传输驱动程序接口)调用,然后使用TDI接口将它们转发到传输驱动程序。在Windows 2003、Windows XP、Windows 2000和Windows NT操作系统中,NetBIOS操作的流程如下:7.2.2 NCB结构体typedef struct _NCB UCHAR ncb_command; UCHAR

9、ncb_retcode; UCHAR ncb_lsn; UCHAR ncb_num; PUCHAR ncb_buffer; WORD ncb_length; UCHAR ncb_callnameNCBNAMSZ; UCHAR ncb_nameNCBNAMSZ; UCHAR ncb_rto; UCHAR ncb_sto; void (CALLBACK *ncb_post)(struct NCB); UCHAR ncb_lana_num; UCHAR ncb_cmd_cplt; UCHAR ncb_reserveX; HANDLE ncb_event;NCB, *PNCB;1ncb_command

10、命令编码可选值说 明NCBACTION非标准NetBIOS 3.0命令NCBADDGRNAME向本地名字表中添加一个组名,组名在网络中必须是唯一的NCBADDNAME向本地名字表中添加一个唯一的名字NCBASTAT获取本地或远程网络适配器的状态。如果指定了此编码,则成员变量_buffer指向填充了ADAPTER_STATUS结构体和NAME_BUFFER结构体数组的缓冲区NCBCALL打开与其他名字之间的会话NCBCANCEL取消之前挂起的命令NCBCHAINSEND向指定的会话伙伴发送两个数据缓冲区的内容NCBCHAINSENDNA向指定的会话伙伴发送两个数据缓冲区的内容,并且不等待对方确认

11、NCBDELNAME从本地名字表中删除一个名字NCBDGRECV获取来自任意名字的数据包NCBDGRECVBC获取来自任意名字的广播数据包NCBDGSEND向指定名字发送数据包NCBDGSENDBC向局域网中的所有计算机发送广播数据包NCBENUM用于枚举LANA编号。如果指定此编码,则成员变量ncb_buffer指定填充了LANA_ENUM结构体的缓冲区。NCBENUM不是标准的NetBIOS 3.0命令NCBFINDNAME决定指定名字在网络中的位置。如果指定此编码,则成员变量_buffer指定填充了FIND_NAME_HEADER结构体和FIND_NAME_BUFFER结构体的缓冲区NC

12、BHANGUP关闭指定的会话NCBLANSTALERT只对Windows Server 2003、Windows XP、Windows 2000和Windows NT等操作系统有效,提示用户持续时间在1分钟以上的局域网故障NCBLISTEN允许一个会话可以被其他名字打开NCBRECV从指定的会话伙伴获取数据NCBRECVANY从指定名字对应的会话中获取数据NCBRESET复位局域网网络适配器NCBSEND向指定的会话伙伴发送数据NCBSENDNA向指定的会话伙伴发送数据,并且不等待对方确认NCBSSTAT获取会话的状态。如果指定了此参数,则成员变量_buffer指向填充了SESSION_HEA

13、DER和SESSION_BUFFER结构体的缓冲区NCBTRACE激活或取消NCB跟踪。此命令目前不被支持NCBUNLINK断开一个网络适配器的连接。此命令只为与之前版本的NetBIOS兼容而提供,但在Windows中无效2ncb_retcode返回编码可选值说 明NRC_GOODRET操作成功NRC_BUFLEN提供了无效的缓冲区长度NRC_ILLCMD提供了无效的命令NRC_CMDTMO命令超时NRC_INCOMP消息不完整,应用程序正在执行其他命令NRC_BADDR缓冲区地址无效NRC_SNUMOUT会话编号越界NRC_NORES没有有效的资源NRC_SCLOSED会话已被关闭NRC_C

14、MDCAN命令被取消NRC_DUPNAME在本地名字表中存在相同的名字NRC_NAMTFUL名字表已满NRC_ACTSES命令已执行完成,指定名字拥有活动的会话,并且不再注册NRC_LOCTFUL本地会话表已满NRC_REMTFUL远端会话表已满,打开会话的请求被拒绝NRC_ILLNN指定了无效的名称编号NRC_NOCALL系统没有发现调用的名字NRC_NOWILD成员变量ncb_name中不允许通配符NRC_INUSE名字已经在远程适配器上使用NRC_NAMERR名字已被删除NRC_SABORT会话非正常结束NRC_NAMCONF检测到名字冲突NRC_IFBUSY接口忙NRC_TOOMANY

15、命令太多,应用程序将在稍后重试命令NRC_BRIDGE成员变量ncb_lana_num没有指定有效的网络编号NRC_CANOCCR执行取消操作后,命令已经结束NRC_CANCELNCBCANCEL命令无效,命令并未取消NRC_DUPENV名字已经被另一个本地进程占用NRC_ENVNOTDEF环境没有被定义,因此必须执行一个重置命令NRC_OSRESNOTAV操作系统资源被耗光,该命令稍候会重试NRC_MAXAPPS应用程序数量超过规定的最大值NRC_NOSAPS没有对NetBIOS有效的服务访问点(SAP,Service Acces Points)NRC_NORESOURCES请求的资源无效N

16、RC_INVADDRESSNCB地址无效NRC_INVDDIDNCB DDID无效NRC_LOCKFAIL尝试锁定用户区域失败NRC_OPENERR当设备驱动器执行打开操作时发生错误。错误编码并不在NetBIOS 3.0中定义NRC_SYSTEM发生系统错误NRC_PENDING异步操作并未结束NCB结构体其他成员变量3ncb_lsn表示本地会话编号。在指定环境中此编号唯一标识一个会话。调用Netbios()函数成功执行了NCBCALL命令后返回此编号。4ncb_num指定本地网络名字编号。调用Netbios()函数成功执行了NCBADDNAME或者NCBADDGRNAME命令后返回此编号。此

17、编号在所有数据包命令和NCBRECVANY命令中使用。5ncb_buffer指向消息缓冲区。可以使用表7.4中的命令访问消息缓冲区。命 令说 明NCBSEND发送消息NCBRECV接收消息NCBSSTAT接收请求状态信息NCB结构体其他成员变量6ncb_length指定消息缓冲区的大小,单位为字节。对于接收命令,此成员变量由Netbios()函数设置,表示接收到的字节数。如果缓冲区长度不正确,则Netbios()函数返回NRC_BUFLEN错误编码。7ncb_callname指定远端应用程序的名字。8ncb_name指定应用程序可以识别的名字。9ncb_rto指定会话执行接收操作的超时时间。将

18、此成员变量指定为0,表示在执行NCBCALL和NCBLISTEN命令时没有超时。超时会影响随后执行的NCBRECV命令。10ncb_sto指定会话执行发送操作的超时时间。将此成员变量指定为0,表示在执行NCBCALL和NCBLISTEN命令时没有超时。超时会影响随后执行的NCBSEND和NCBCHAINSEND命令。11ncb_post指定异步命令完成后需调用的例程地址。12ncb_lana_num指定LANA编号。13ncb_cmd_cplt指定命令完成标识。14ncb_reserve保留字段,必须为0。15ncb_event指定事件对象的句柄。当执行异步命令时,事件对象被设置为未受信状态;

19、当异步命令完成后,事件对象被设置为受信状态,这样就可以执行对应的事件处理程序了。7.2.3 其他常用NetBIOS结构体1LANA_ENUM结构体2ADAPTER_STATUS结构体3NAME_BUFFER结构体4ASTAT结构体1LANA_ENUM结构体LANA_ENUM结构体中包含当前逻辑网络适配器的数量。当一个物理网络适配器绑定到一个网络协议时,就对应一个逻辑网络适配器。执行NCB命令NCBENUM可以向LANA_ENUM结构体中填充逻辑网络适配器的个数和逻辑网络适配器编号,此时NCB结构体中的ncb_buffer成员变量指向LANA_ENUM结构体。LANA_ENUM结构体的定义代码如

20、下:typedef struct _LANA_ENUM UCHAR length; UCHAR lanaMAX_LANA;LANA_ENUM, *PLANA_ENUM;参数说明如下:length,系统中包含的逻辑网络适配器数量。lanaMAX_LANA,系统中包含的逻辑网络适配器编号数组。2ADAPTER_STATUS结构体ADAPTER_STATUS结构体中包含网络适配器的信息。NCB结构体的ncb_buffer成员变量指定该结构体。通常,ADAPTER_STATUS结构体的后面跟着很多NAME_BUFFER结构体。ADPATER_STATUS结构体的定义代码如下:typedef struc

21、t _ADAPTER_STATUS UCHAR adapter_address6; UCHAR rev_major; UCHAR reserved0; UCHAR adapter_type; UCHAR rev_minor; WORD duration; WORD frmr_recv; WORD frmr_xmit; WORD iframe_recv_err; WORD xmit_aborts; DWORD xmit_success; DWORD recv_success; WORD iframe_xmit_err; WORD recv_buff_unavail; WORD t1_timeou

22、ts; WORD ti_timeouts; DWORD reserved1; WORD free_ncbs; WORD max_cfg_ncbs; WORD max_ncbs; WORD xmit_buf_unavail; WORD max_dgram_size; WORD pending_sess; WORD max_cfg_sess; WORD max_sess; WORD max_sess_pkt_size; WORD name_count; ADAPTER_STATUS, *PADAPTER_STATUS;ADAPTER_STATUS结构体参数说明adapter_address,指定网

23、络适配器的地址。rev_major,指定发布软件的主版本号。例如,如果发布版本号为IBM NetBIOS 3.x,则rev_major的值为3。reserved0,保留字段,始终为0。adapter_type,指定网络适配器的类型。如果是令牌环适配器,则该值为0 xFF;如果是以太网适配器,则该值为0 xFE。rev_minor,指定发布软件的副版本号。例如,如果发布版本号为IBM NetBIOS 3.0,则rev_minor的值为0。duration,指定报告的时间周期,单位为分钟。frmr_recv,指定接收到的FRMR(帧拒绝)帧数量。frmr_xmit,指定传送的FRMR帧数量。ifr

24、ame_recv_err,指定接收到的错误帧数量。xmit_aborts,指定终止传输的包数量。xmit_success,指定成功传输的包数量。recv_success,指定成功接收的包数量。iframe_xmit_err,指定传输的错误帧数量。recv_buff_unavail,指定缓冲区无法为远程计算机提供服务的次数。t1_timeouts,指定DLC(Data Link Control,数据链路控制) T1计时器超时的次数。ti_timeouts,指定ti非活动计时器超时的次数。t1计时器用于检测断开的连接。reserved1,保留字段,始终为0。free_ncbs,指定当前空闲的网络控

25、制块的数量。max_dgram_size,指定数据包的最大大小,该值至少为512字节。pending sess,指定挂起会话的数量。max_cfg_sess,指定配置的最大挂起会话数量。max_sess_pkt_size,指定会话数据包的最大大小。name_count,指定本地名字表中名字的数量。3NAME_BUFFER结构体结构体NAME_BUFFER中包含本地网络名字信息。当应用程序执行NCBASTAT命令时,可以获取ADAPTER_STATUS结构体及其后面的NAME_BUFFER结构体。NAME_BUFFER结构体。typedef struct _NAME_BUFFER UCHAR n

26、ameNCBNAMSZ; UCHAR name_num; UCHAR name_flags;NAME_BUFFER, *PNAME_BUFFER;参数说明如下:name,指定本地网络名字,该值对应NCB结构体的ncb_name字段。name_num,指定本地网络名字的数量,该值对应NCB结构体的ncb_num字段。name_flags,指定名字表条目的当前状态。4ASTAT结构体ASTAT结构体用于描述网络适配器的状态和名字信息,定义代码如下:typedef struct ADAPTER_STATUS adapt; NAME_BUFFER NameBuff30; ASTAT;参数adapt表示

27、网络适配器的状态信息,参数NameBuff表示网络适配器中保存的本地网络名字信息。7.2.4 Netbios()函数Netbios()函数用于解释和执行指定的网络控制块(NCB),语法如下:UCHAR Netbios( _in PCNB pcnb);参数pcnb是指定NCB结构体的指针,用于描述网络控制块。如果执行同步请求命令,则函数的返回值为NCB结构体的编码。该值也保存在NCB结构体的ncb_retcode字段中。异步请求的返回值有以下两种情况:(1)如果Netbios()返回时异步命令已经完成,则返回值为NCB结构体的编码,这与同步请求的返回值相同。(2)如果Netbios()返回时异步

28、命令尚未完成,则返回值为0。如果pncb参数中指定的地址无效,则返回NRC_BADNCB。如果NCB结构体中ncb_length字段指定的缓冲区长度不正确,或者缓冲区不允许执行写操作,则返回NRC_BUFLEN。7.2.5 获取LANA上的所有NetBIOS名字【例7.1】编写程序,向本地名字表中添加一个名字UNIQUENAME,然后列出指定LANA0中定义的所有NetBIOS名字。第1个名字是本地计算机名,第2个名字是本地计算机所属的工作组名,最后一个名字是新添加的NetBIOS名字。下面对本实例中的代码进行介绍。1引用的头文件和库文件#include stdafx.h#include #i

29、nclude #include #include #pragma comment(lib, netapi32.lib)其中Nb30.h是定义NetBIOS结构体和函数的头文件,而netapi32.lib则是NetBIOS编程所需要的静态库文件。2常量和宏定义#define LANANUM 0/ 本实例中操作的LANA编号/ 本实例中添加的名字,注意不能与本地计算机重名#define LOCALNAME UNIQUENAME“#define NBCheck(x) if (NRC_GOODRET != x.ncb_retcode) printf(Line %d: Got 0 x%x from Ne

30、tBios()n, _LINE_, x.ncb_retcode); 在使用宏NBCheck时,使用ncb结构体为参数。ncb结构体的ncb_retcode参数表示调用Netbios()函数的返回值。如果返回值不等于NRC_GOODRET,则表示函数调用失败,需要输出发生错误的行号和函数返回值,以便用户定位问题。3NBReset()函数BOOL NBReset (int nLana, int nSessions, int nNames) NCB ncb; / 初始化ncb结构体 memset (&ncb, 0, sizeof (ncb);/ 清空ncb结构体 ncb.ncb_command =

31、NCBRESET;/ 执行NCBRESET命令 ncb.ncb_lsn = 0;/ 分配新的lana_num资源 ncb.ncb_lana_num = nLana;/ 设置lana_num资源 ncb.ncb_callname0 = nSessions;/ 设置最大会话数 ncb.ncb_callname2 = nNames;/ 设置最大名字数 Netbios (&ncb);/ 执行NCBRESET命令 NBCheck (ncb);/ 如果执行结果不正确,则输出ncb.ncb_retcode / 如果成功返回TRUE,否则返回FALSE return (NRC_GOODRET = ncb.nc

32、b_retcode);4NBAddName()函数BOOL NBAddName (int nLana, LPCSTR szName) NCB ncb; memset (&ncb, 0, sizeof (ncb);/ 清空ncb结构体 ncb.ncb_command = NCBADDNAME;/ 执行NCBDDNAME命令 ncb.ncb_lana_num = nLana;/ 设置lana_num / 将szName赋值到ncb.ncb_name中 MakeNetbiosName (char*) ncb.ncb_name, szName); Netbios (&ncb);/ 执行NCBRESET

33、命令 NBCheck (ncb); / 如果执行结果不正确,则输出ncb.ncb_retcode/ 如果成功返回TRUE,否则返回FALSE return (NRC_GOODRET = ncb.ncb_retcode);MakenetbiosName()函数/ 将szSrc中的名字赋值到achDest中,名字的长度为NCBNAMESZ/ 如果不足,则使用空格补齐void MakeNetbiosName (char *achDest, LPCSTR szSrc) int cchSrc; cchSrc = lstrlen (szSrc); if (cchSrc NCBNAMSZ) cchSrc =

34、 NCBNAMSZ; memset (achDest, , NCBNAMSZ); memcpy (achDest, szSrc, cchSrc);5NBAdapterStatus()函数/ 获取指定LANA的网络适配器信息/ nLana, LANA编号/ pBuffer, 获取到的网络适配器缓冲区/ cbBuffer, 缓冲区长度/ szName, 主机名字BOOL NBAdapterStatus (int nLana, PVOID pBuffer, int cbBuffer, LPCSTR szName) NCB ncb; memset (&ncb, 0, sizeof (ncb);/ 清空

35、ncb结构体 ncb.ncb_command = NCBASTAT;/ 设置执行NCBASTAT命令 ncb.ncb_lana_num = nLana;/ 设置LANA编号 / 将获取到的数据保存到参数pBuffer中 ncb.ncb_buffer = (PUCHAR) pBuffer; ncb.ncb_length = cbBuffer;/ 设置缓冲区长度 / 设置参数ncb.ncb_callname MakeNetbiosName (char*) ncb.ncb_callname, szName); Netbios (&ncb);/ 执行NetBIOS命令 NBCheck (ncb);/

36、如果执行不成功,则输出返回值 / 如果成功返回TRUE,否则返回FALSE return (NRC_GOODRET = ncb.ncb_retcode);6NBListNames()函数BOOL NBListNames (int nLana, LPCSTR szName) int cbBuffer;/ 获取数据的缓冲区 ADAPTER_STATUS *pStatus;/ 保存网络适配器的信息 NAME_BUFFER *pNames;/ 保存本地名字信息 HANDLE hHeap;/ 当前调用进程的堆句柄 / 当前调用进程的堆句柄 hHeap = GetProcessHeap(); / 分配可能

37、的最大缓冲区空间 cbBuffer = sizeof (ADAPTER_STATUS) + 255 * sizeof (NAME_BUFFER);/ 为pStatus分配空间 pStatus = (ADAPTER_STATUS *) HeapAlloc (hHeap, 0, cbBuffer); if (NULL = pStatus) return FALSE; / 获取本地网络适配器信息,结果保存到pStatus中 if (!NBAdapterStatus (nLana, (PVOID) pStatus, cbBuffer, szName) HeapFree (hHeap, 0, pStat

38、us); return FALSE; / 列出跟在ADAPTER_STATUS结构体后面的名字信息 pNames = (NAME_BUFFER *) (pStatus + 1); for (int i = 0; i name_count; i+) printf (t%.*sn, NCBNAMSZ, pN);/ 释放分配的堆空间 HeapFree (hHeap, 0, pStatus); return TRUE;6NBListNames()函数程序的运行过程如下:获取当前进程的堆句柄,然后在堆上分配可能的最大缓冲区空间,即一个ADAPTER_STATUS结构体占用的空间加上2

39、55个NAME_BUFFER结构体占用的空间。在执行NCBASTAT命令时,可以返回一个ADAPTER_STATUS结构体和一组(最多255个)NAME_BUFFER结构体。调用NBAdapterStatus()函数,获取本地网络适配器信息,结果保存到pStatus结构体中。在pStatus结构体后面紧跟着的是一组NAME_BUFFER结构体,将pName指针指向第1个NAME_BUFFER结构体。pStatus-name_count中保存着pStatus后面NAME_BUFFER结构体的数量。使用for语句遍历这些结构体,输出NAME_BUFFER结构体中的名字信息。释放分配的堆空间。7_t

40、main()函数int _tmain(int argc, _TCHAR* argv)/ 初始化if (!NBReset (LANANUM, 20, 30) return -1;/ 向本地名字表中添加UNIQUENAMEif (!NBAddName (LANANUM, LOCALNAME) return -1;/ 列出本地名字表中的名字if (!NBListNames (LANANUM, LOCALNAME) return -1;printf (Succeeded.n);system(pause);return 0;7.2.6 获取网络适配器上的MAC地址【例7.2】编写程序,获取网络适配器上的

41、MAC地址。1引用的头文件和库文件#include stdafx.h#include #include #include #pragma comment(lib, netapi32.lib)2结构体ASTAT结构体ASTAT用于定义网络适配器状态和名字表信息,代码如下:typedef struct _ASTAT_ ADAPTER_STATUS adapt; NAME_BUFFER NameBuff 30;ASTAT, * PASTAT;ASTAT Adapter;ASTAT结构体变量Adapter用于保存执行NCBASTAT命令获取到的网络适配器状态和名字表信息。3_tmain()函数int

42、_tmain(int argc, _TCHAR* argv)NCB ncb;/ NCB结构体,用于设置执行的NetBIOS命令和参数 UCHAR uRetCode;/ 执行Netbios()函数的返回值 memset( &ncb, 0, sizeof(ncb) );/ 初始化ncb结构体 ncb.ncb_command = NCBRESET;/ 设置执行NCBRESET ncb.ncb_lana_num = 0;/ 设置LANA编号 / 调用Netbios()函数,执行NCBRESET命令 uRetCode = Netbios( &ncb ); / 输出执行NCBRESET命令的结果 prin

43、tf( The NCBRESET return code is: 0 x%x n, uRetCode ); memset( &ncb, 0, sizeof(ncb) );/ 初始化ncb ncb.ncb_command = NCBASTAT;/ 执行NCBASTAT命令 ncb.ncb_lana_num = 0;/ 设置LANA编号 / 设置执行NCBASTAT命令的参数,将获取到的网络适配器数据保存到Adapter结构体中 memcpy( &ncb.ncb_callname, * , 16 ); ncb.ncb_buffer = (UCHAR*) &Adapter; ncb.ncb_leng

44、th = sizeof(Adapter); / 调用Netbios()函数,执行NCBASTAT命令 uRetCode = Netbios( &ncb ); printf( The NCBASTAT return code is: 0 x%x n, uRetCode );3_tmain()函数 if ( uRetCode = 0 ) / 输出MAC地址 printf( The Ethernet Number is: %02x-%02x-%02x-%02x-%02x-%02xn, Adapter.adapt.adapter_address0, Adapter.adapt.adapter_addr

45、ess1, Adapter.adapt.adapter_address2, Adapter.adapt.adapter_address3, Adapter.adapt.adapter_address4, Adapter.adapt.adapter_address5 ); system(pause); return 0;程序的运行过程执行NCBRESET命令,清空本地的名字表和会话表。执行NCBASTAT命令获取网络适配器信息。依次打印数组Adapter.adapt.adapter_address中的元素值,即输出MAC地址。7.3 在程序中实现NBTSTAT命令的功能7.3.1 本实例的工作原

46、理7.3.2 定义的结构体7.3.3 为获取NetBIOS信息而定义的函数7.3.4 实现NBTSTAT命令功能的主函数7.3.1 本实例的工作原理7.3.2 定义的结构体1names结构体2workstationNameThreadStruct结构体1names结构体names结构体用于接收目标计算机发送回来的名字信息,代码如下:struct namesunsigned char nb_name16;unsigned short name_flags;参数nb_name表示接收到的名字,name_flags用于标识名字的含义。2workstationNameThreadStruct结构体wo

47、rkstationNameThreadStruct结构体用于保存获取NetBIOS信息的套接字和IP地址列表,代码如下:struct workstationNameThreadStructSOCKET s;std:map *ips;参数s指定发送和接收NetBIOS数据包的套接字,参数ips指定获取NetBIOS信息的IP地址列表。7.3.3 为获取NetBIOS信息而定义的函数为了获取远程计算机的NetBIOS信息,在程序中需要向指定的IP地址发送NetBIOS请求包,然后创建一个线程来接收返回的NetBIOS回应包,最后将回应包中的信息解析成需要的数据。本节介绍实现这些功能的3个函数。1G

48、etHostInfo()函数2NetBiosRecvThreadProc()函数3GetEthernetAdapter()函数1GetHostInfo()函数void GetHostInfo(std:map &ips, int timeout) SOCKET sock;/ 通信套接字 struct sockaddr_in origen;/ 本地地址 WSADATA wsaData;/ Windows Sockets环境变量 / 初始化Windows Sockets环境 if(WSAStartup(MAKEWORD(2,1),&wsaData) != 0) return; / 创建TCP/IP套

49、接字 if(sock = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP)=INVALID_SOCKET) return; / 设置超时时间 if(setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout)=SOCKET_ERROR) / 释放资源 closesocket(sock); WSACleanup(); return; 1GetHostInfo()函数/ 将套接字绑定到本地地址和端口memset(&origen,0,sizeof(origen);origen.sin_fam

50、ily = AF_INET;origen.sin_addr.s_addr = htonl (INADDR_ANY);origen.sin_port = htons (0);if (bind (sock, (struct sockaddr *) &origen, sizeof(origen) 0) / 释放资源closesocket(sock);WSACleanup();return;/ 为创建接收线程准备数据workstationNameThreadStruct unionStruct;unionStruct.ips = &ips;unionStruct.s = sock;1GetHostIn

51、fo()函数/ 启动线程等待接收NetBIOS回应包DWORD pid;HANDLE threadHandle = CreateThread(NULL, 0, NetBiosRecvThreadProc,(void *)&unionStruct, 0, &pid);/ 依次向ips中的每个IP地址的端口发送NetBIOS请求包(保存在input字符数组中)std:map:iterator itr;for(itr=ips.begin();itr!=ips.end();itr+)char input=x80 x94x00 x00 x00 x01x00 x00 x00 x00 x00 x00 x20

52、 x43x4bx41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x00 x00 x21x00 x01;struct sockaddr_in dest;/ 发送NetBios请求信息memset(&dest,0,sizeof(dest);dest.sin_addr.s_addr = itr-first;dest.sin_family = AF_INET;dest.sin_port = htons(137);sendto (sock, input, sizeof(input)-1, 0, (struct sockaddr *)&dest, sizeof (dest);1GetHostInfo()函数/ 等待接收线程NetBiosRecvThreadProc结束DWORD ret = WaitForSingleObject(threadHandle, timeout * 4); / 如果超时,则结束接收线程NetBiosRecvThreadProcif(ret = WAIT_TIME

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论