加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 【No

【No.0030】WINDOWS网络编程

【No

期待Jiao
2008-12-06 0人阅读 举报 0 0 暂无简介

简介:本文档为《【Nopdf》,可适用于IT/计算机领域

下载本书第一部分讲述的是传统的网络接口NetBIOS、重定向器以及通过重定向器进行的各类网络通信。尽管本书大部分内容均围绕Winsock编程这一主题展开但是API比起Winsock来仍然具有某些独到之处。其中第章探讨的是NetBIOS接口它和Winsock类似也是一种与协议无关的网络API。NetBIOS提供了异步调用同时兼容于较老的操作系统如OS和DOS等等。第章讨论了重定向器的问题它是接下去的两个新主题邮槽(第章)和命名管道(第章)的基础。重定向器提供了与传输无关的文件输入/输出方式。邮槽是一种简单的接口可在Windows机器之间实现广播和单向数据通信。最后命名管道可建立一种双向信道这种信道提供了对Windows安全通信的支持。第章NetBIOS“网络基本输入/输出系统”(NetworkBasicInputOutputSystem,NetBIOS)是一种标准的应用程序编程接口(API)年由Sytek公司专为IBM开发成功。NetBIOS为网络通信定义了一种编程接口但却没有详细定义物理性的“帧”如何在网上传输。年IBM创制了NetBIOS扩展用户接口(NetBIOSExtendedUserInterface,NetBEUI)它同NetBIOS接口集成在一起终于构成了一套完整的协议。由于NetBIOS接口变得愈来愈流行所以各大厂商也开始在其他如TCPIP和IPXSPX的协议上实施NetBIOS编程接口。到目前为止全球已有许多平台和应用程序需要依赖于NetBIOS其中包括WindowsNT、Windows、Windows和Windows的许多组件。注意WindowsCE并不支持NetBIOSAPI只是用TCPIP作为其传送协议并同时支持NetBIOS的名字与名字解析。WinNetBIOS接口向后兼容于早期的应用程序。本章要讨论的是NetBIOS编程基础。首先向大家介绍的是NetBIOS的一些基本知识从NetBIOS的名字及LANA编号开始接着我们围绕NetBIOS提供的基本服务展开讨论比如面向会话和“无连接”通信等等。在每一节都展示了一个简单的客户机和服务器示例。在本章最后我们陈列了程序员需留意的一系列陷阱以及易犯的错误。在本书的附录A中大家可找到一份命令索引其中对每个NetBIOS命令都进行了总结包括必要的参数以及对其行为的简单说明。OSI网络模型“开放系统互连”(OSI)模型从一个很高的层次对网络系统进行了描述。OSI模型总共包含了七层。从最顶部的“应用层”开始一直到最底部的“物理层”这七个层完整阐述了最基本的网络概念。图展示的正是OSI模型的样子。第一部分传统网络API图OSI网络模型对应OSI模型NetBIOS主要在会话和传输层发挥作用。MicrosoftNetBIOS如前所述NetBIOSAPI实施方案适用于为数众多的网络协议使得编程接口“与协议无关”。换言之假如根据NetBIOS规范设计了一个应用程序它就能在TCPIP、NetBIOS甚至IPXSPX上运行。这是一项非常有用的特性因为对一个设计得当的NetBIOS应用程序来说它几乎能在任何机器上运行无论机器连接的物理网络是什么。然而我们也必须留意几个方面的问题。要想使两个NetBIOS应用(程序)通过网络进行正常通信那么对它们各自运行的机器来说至少必须安装一种两者通用的协议。举个例子来说假定小张的机器只安装了TCPIP而小马的机器只安装了NetBEUI那么对小张机器上的NetBIOS应用来说便无法同小马机器上的应用进行通信。除此以外只有部分协议实施了NetBIOS接口。MicrosoftTCPIP和NetBEUI在默认情况下已提供了一个NetBIOS接口然而IPXSPX却并非如此。为此微软专门提供了一个IPXSPX版本在其中实现了该接口。在设计网络时这个问题必须注意。安装协议时具有NetBIOS能力的IPXSPX协议通常会自动提醒你注意这方面的问题。例如Windows提供的协议本身就叫作“NWLinkIPXSPXNetBIOS兼容传送协议”。而在Windows和Windows中请留意IPXSPX协议属性对话框其中有一个特殊的复选框名为“希望在IPXSPX上启用NetBIOS”。另外要注意的一个重要问题是NetBEUI并非是一种“可路由”协议。假定在客户机和服务器之间存在一个路由器那么这种协议在两部机器上的应用便无法沟通。收到数据包后路由器便会将其“无情地”地抛弃。TCPIP和IPXSPX则不同它们均属“可路由”协议不会出现这方面的问题。要注意的是假如你需要在很大程度上依靠NetBIOS那么在配置网络时至少应安装一种可路由的传送协议。要想深入了解各种协议的特征以及相应的注意事项请参阅第章。LANA编号从编程角度思考大家或许会觉得奇怪传送协议与NetBIOS如何对应起来呢?答案便在于LAN适配器(LANadapter,LANA)编号它是我们理解NetBIOS的关键。在最初的NetBIOS实施方案中每张物理网卡都会分配到一个独一无二的值:即LANA编号。但到Win下这种做法便显得有些问题。因为对一个工作站来说它完全可能同时安装了多种网络协议也可能安装了多张网卡。计计第一部分附传统网络API下载应用层层描述为用户提供相应的界面以便使用提供的连网功能完成数据的格式化控制两个主机间的通信链路(开放、操作和关闭)提供数据传输服务(可靠或不可靠)在两个主机之间提供一套定址寻址机制同时负责数据包的路由选择控制两个主机间的物理通信链路:同时还要负责对数据进行整形以便在物理媒体上传输物理媒体负责以一系列电子信号的形式传出数据表示层会话层传输层网络层数据链路层物理层每个LANA编号对应于网卡及传输协议的唯一组合。例如假定某工作站安装了两张网卡以及两种具有NetBIOS能力的传输协议(如TCPIP和NetBEUI)那么总共就有四个LANA编号。下面是一种对应关系的例子:TCPIP网卡NetBEUI网卡TCPIP网卡NetBEUI网卡通常LANA编号的范围在到之间除LANA之外操作系统并不按某种固定的顺序来分配这些编号。那么LANA有什么特殊含义呢?LANA代表的是“默认”LANA!NetBIOS问世早期许多应用都采用硬编码的形式只依赖LANA进行工作。在那时大多数操作系统也只支持一个LANA编号。考虑到向后兼容的目的我们可将LANA人工分配给一种特定的协议。在Windows和Windows中通过选择控制面板中的“网络”图标可访问一种网络协议的“属性”对话框。在“网络”对话框中选择“配置”选项卡再从网络组件列表中选择一种网络协议按下“属性”按钮即可。对具有NetBIOS能力的每一种协议来说其属性对话框的“高级”选项卡都有一个“设成默认的通信协议”复选框。若选中这个复选框会重新安排协议的绑定使默认协议能够分配到LANA。注意在任何时候只能有一种协议才能选中这个复选框。由于Windows和Windows具有所谓的“即插即用”功能所以我们没有其他办法可对协议的编号顺序进行更改。WindowsNT则允许用户在设置NetBIOS时拥有更大的灵活性。在“网络”对话框的“服务”选项卡中可从“网络服务”列表框内选择NetBIOS接口然后点按“属性”按钮。随后便会出现“NetBIOS配置”对话框在这里可针对每一对网卡/传输协议的组合分配各自的LANA编号。在这个对话框中每张网卡都以其驱动程序的名字加以标识但协议名称却显得有些暧昧。在图中我们展示了NetBIOS配置对话框的样子。单击其中的“Edit”(编辑)按钮便可为每种协议单独分配LANA编号。Windows也允许我们单独分配LANA编号。在控制面板中双击“网络和拨号连接”图标。随后从“高级”菜单中选择“高级设置”然后在高级设置对话框中选择“LANA编号”选项卡。图NetBIOS配置对话框。这是一部多宿主机器安装了两张网卡和三种传输协议:TCPIP(NetBT)、NetBEUI(Nbf)以及IPXSPX(NwlnkNb)第章计NetBIOS计计下载要想设计出一个“健壮”的NetBIOS应用必然需要让自己的代码能对任意LANA编号上的连接进行控制。例如假定小马编写了一个NetBIOS服务器应用对LANA上的客户机进行监听。在小马的机器(即服务器)上LANA正好对应于TCPIP。后来小张需要编写一个客户端应用同小马的服务器通信所以他决定让自己的程序通过工作站的LANA建立连接。然而小张工作站上的LANA对应于NetBEUI。这样一来两个应用相互间均无法通信尽管两者都安装了TCPIP和NetBEUI。为纠正协议的这种差异小马的服务器应用程序必须对小马工作站上每个可能的LANA编号上的客户机连接进行“监听”。类似地小张的客户机应用程序需要针对本机每个可能的LANA编号尝试在其上面的连接。只有这样小马和小张才能保证自己的应用尽最大可能成功通信。当然尽管我们需要在代码中对任何LANA编号上的连接进行控制但并不表示能够百分之百地成功。假如两台机器根本就没有安装一种共通的协议那么无论如何都是不能成功的!NetBIOS名字现在我们知道了LANA编号是什么接着再来讨论NetBIOS名字(名称)的问题。对一个进程(或“应用”、“应用程序”)来说它会注册自己希望与其通信的每个LANA编号。一个NetBIOS名字长度为个字符其中第个字符是为特殊用途保留的。在名字表内添加一个名字时应将名字缓冲区初始化成空白。在Win环境中针对每个可用的LANA编号每个进程都会为其维持一张NetBIOS名字表。若为LANA增添一个名字意味着你的应用程序只能在LANA上同客户机建立连接。对每个LANA来说能够添加的名字的最大数量是编号从到(和由系统保留)。然而每种操作系统都设置了一个低于的最大默认值。重设每个LANA编号时我们可对此默认值进行修改。另外NetBIOS名字共有两种类型:唯一名字和组名。“唯一名字”意味着它是独一无二的:网络上不能再有其他任何进程来注册这个名字。如果一台机器已注册了某名字那么在你注册该名字时便会收到一条“重复名字”出错提示。大家或许已经知道微软网络中的机器名采用的便是NetBIOS名字。机器启动时会将自己的名字注册到本地的“Windows互联网命名服务器”(WINS)。如果事前已有另一台机器注册了同样的名字WINS服务器便会报错。WINS服务器维护着已注册的所有NetBIOS名字的一个列表。除此以外随名字一道还可保存协议特有的一些信息。比如在TCPIP网络中WINS同时维护着NetBIOS名字以及注册那个名字的IP地址(亦即相应的机器)。假如配置网络时未为其分配一个WINS服务器那么如何检查名字是否重复呢?这时便要采用在整个网络内“发广播”的形式。当一名发送者向全网络发出一条特殊的广播消息时如果没有其他机器回应这条消息便允许发送者使用该名字。而在另一方面“组名”的作用是将数据同时发给多个接收者或者相反接收发给多个接收者的数据。组名并非一定要“独一无二”它主要用于多播(多点发送)数据通信。在NetBIOS名字中第个字符用于区分不同的微软网络服务。各种网络服务和组名需要用一个WINS服务器完成注册。要么由配置了WINS功能的计算机进行名字的直接注册要么由那些尚未配置WINS功能的计算机通过在本地子网内进行广播注册。Nbtstat命令是一个非常有用的工具可用它获取与本地(或远程)计算机上注册的NetBIOS名字有关的信息。在表展示的例子中Nbtstatn命令可针对用户“Davemac”生成这个已注册的NetBIOS名字的列表。Davemac登录进入的那部计算机已被配置成一个主域控制器而且运行的是计计第一部分附传统网络API下载WindowsNTServer操作系统且已安装了Internet信息服务器(IIS)。表NetBIOS名字表名字第个字节名字类型服务DAVEMAC<>唯一工作站服务名DAVEMAC<>唯一服务器服务名DAVEMACD<>成组域名DAVEMACD<C>成组域控制器名DAVEMACD<B>唯一主控浏览器名DAVEMAC<>唯一发信者名Inet~Services<C>成组Internet信息服务器组名IS~DAVEMAC<>唯一Internet信息服务器唯一名DAVEMAC<BF>唯一网络监视器名字只有在安装了TCPIP协议的前提下才会安装Nbtstat命令。该工具亦可用来查询远程机器的名字表方法是在远程机器的名字后面接上一个a参数或在远程机器的IP地址后接上一个A参数。在表中我们总结了各种不同的Microsoft网络服务为唯一NetBIOS计算机名追加的默认第个字节值。表唯一名字标识符第个字节含义<>工作站服务名。通常它对应于NetBIOS计算机名<>收发消息时采用的信使服务名。WINS服务器会将这个名字注册成WINS客户机上的信使服务并通常追加到计算机名后面以及当前登录到计算机的用户名的后面<B>域主控浏览器名。这个名字用于标识主域控制器并指出用什么客户机和其他浏览器同域主控浏览器取得联系<>远程访问服务(RAS)服务器服务<F>网络动态数据交换(NetDDE)服务<>用于为文件共享提供“共享点”的服务器服务名<>RAS客户机<BE>网络监视器代理<BF>网络监视器工具表则列出了在常用的一系列NetBIOS组名后追加的默认第个字节字符。如此多的标识符很易使人产生混淆很难真正记住。所以请考虑把它作为一个“速查表”或“索引”使用。大家或许不应在自己的NetBIOS名字中使用它们。为防止偶然同你的NetBIOS名字发生冲突最好避免使用唯一名字标识符。对于组名恐怕更要引起高度注意假如你的名字同一个已有的组名相同那么不会产生任何错误提示。若发生这种情况结果就是会收到原本发给其他人的数据。表组名标识符第个字节含义<C>一个域组名在这个组内包含了已注册域名的一系列计算机的特定地址。由域控制器来注册这个名字。WINS将它当作一个域组看待:组内每个成员必须单独更新自己的名字。域组最多只能包容个名字。若复制的一个静态C名字同另一个WINS服务器上的某个动态C名字发生冲突便会增加成员的一个“联合”同时将记录标定为“静态”。假如记录是静态的组内成员便不必定时刷新自己的IP地址第章计NetBIOS计计下载(续)第个字节含义<D>指定一个主控浏览器的名字客户机通过它访问主控浏览器。在一个子网上只能有一个主控浏览器。WINS服务器会对域名注册作出“正”(肯定)响应但却不会将域名保存在自己的数据库中。假如一台计算机向WINS服务器送出一个域名查询则WINS服务器会返回一个“负”(否定)响应。若送出域名查询的那台计算机已被配置成h节点或m节点便会随之广播那个查询以解析出正确的名字。客户机解析名字的方法是由节点的类型决定的。如客户机配置成b节点解析便会送出广播包以便广告并解析出NetBIOS名字。p节点解析采用与WINS服务器的点到点通信方式。而m节点属于b及p节点的一种混合形式:首先使用的是b节点如有必要再接着使用p节点。最后一种解析方式是h节点亦称“混合模式”。它无论如何都会先尝试使用p节点注册和解析然后只有在解析失败的前提下才会换用b节点。Windows操作系统默认为h节点<E>一个普通组名。浏览器可向这个名字发送广播数据并通过对它的监听来挑选一个主控浏览器。这些广播面向的是本地子网绝对不应通过路由器传输<>一个Internet组名。这种类型的名字由WINS服务器进行注册以便为了管理方面的目的来标定特定的计算机组。例如“printersg”可以是一个注册的组名用于标定由打印服务器构成的一个管理性组MSBROWSE不再是单独一个追加的第位字符“MSBROWSE”需要追加到一个域名后面并在本地子网上进行广播向其他主控浏览器通告这个新增的域NetBIOS特性NetBIOS同时提供了“面向连接”服务以及“无连接”服务。面向连接的服务是指它允许两个客户机相互间建立一个会话或者说建立一个“虚拟回路”。这种“会话”实际是一种双向的通信数据流通信的每一方都可向另一方发送消息。面向连接的服务可担保在两个端点之间任何数据都能准确无误地传送。在这种服务中服务器通常将自己注册到一个已知的名字下。客户机会搜寻这个名字以便建立与服务器的通信。就拿NetBIOS的情况来说服务器进程会针对想通过它建立通信的每一个LANA编号将自己的名字加入与其对应的名字表。而对位于其他机器上的客户来说就可将一个服务名解析成机器名然后要求同服务器进程建立连接。大家可以看到为建立这种虚拟回路必须采取一些适当的步骤。而且在初次建立连接的时候还会牵涉到一些额外的开销。“面向连接”或“面向会话”的通信可保证通信具有极高的可靠性而且数据包的收发顺序亦能确保正确无误。然而它仍然是一种“以消息为基础”的服务。也就是说假如已连接好的某个客户机执行一个“读”命令那么服务器在流中仍然只会返回一个数据包尽管客户机此时提供了一个足够大的缓冲区可同时容下几个包!“无连接”或数据报服务中服务器并不将自己注册到一个特定的名下而只是由客户机收集数据然后将其送入网络事前不必先建好任何连接(即无连接)。对于数据的目的地址客户机会将其定义成服务器相应进程对应的NetBIOS名字。这种类型的服务不提供任何保障但同面向连接的服务相比却可有更好的性能如在使用数据报服务(无连接服务)时省下了建立连接所需的开销。例如客户机可能向服务器兴冲冲地一下子发出数千字节的数据但那台服务器早在一两天前便已当机了。除非依赖自服务器传来的响应否则客户机永远都收不到任何错误提示(在这种情况下假如在一个特定的时间段内没有收到任何响应便计计第一部分附传统网络API下载可认为服务器出了故障)。数据报服务既不能保证数据传输的可靠性也不能保证数据包的传送顺序正确无误。NetBIOS编程基础现在我们已理解了NetBIOS的一些基本概念接下来要讨论的是NetBIOSAPI的设置这其实非常简单因为只有一个函数:UCHARNetbios(PNCBpNCB)用于NetBIOS的所有函数声明、常数等等均是在头文件Nbh内定义的。若想连接NetBIOS应用唯一需要的库是Netapilib。该函数最重要的特征便是pNCB这个参数它对应于指向某个网络控制块(NCB)的一个指针。在那个NCB结构中包含了为执行一个NetBIOS命令相应的Netbios函数需要用到的全部信息。该结构的定义如下:注意并不是在对NetBIOS的每次调用中都需要用到该结构内的全部成员有些数据字段对应的是输出参数(换言之自Netbios调用返回之后才能设置)。在此提醒大家重要的一点:进行任何Netbios调用之前不要一开始就填写结构内的各个成员而应先将这个NCB结构清零!请看看表的总结其中解释了每个字段的用法。此外本书附录A的命令索引对每个NetBIOS命令都进行了详尽总结并解释了它需要用到NCB结构中的哪些字段以及哪些字段可选。表NCB结构成员字段定义ncbcommand指定要执行的NetBIOS命令。许多命令都可同步或异步与ASYNCH(X)标志以及命令进行按位OR(或)运算ncbretcodef指定操作的返回代码。在一个异步操作进行期间函数会将该值设为NRCPENDINGncblsn对应一个本地会话编号与当前环境内的一次会话有着唯一对应的关系。成功执行了一次NCBCALL或NCBLISTEN命令后函数会返回一个新的会话编号ncbnum指定本地名字的编号。伴随NCBADDNAME或NCBADDGRNAME命令的每一次调用都会返回一个新编号。针对所有数据报命令都必须使用一个有效的编号ncbbuffer指向数据缓冲区。对那些需要发送数据的命令该缓冲区包含了要送出的实际数据而对那些需要接收数据的命令则包含了要从Netbios函数返回的数据。对其第章计NetBIOS计计下载(续)字段定义他命令来说如NCBENUM缓冲区便是预定义的结构LANAENUMncblength以字节数为单位指定缓冲区的长度。对于接收命令来说Netbios会将该值设为收到的字节数。若指定的缓冲区不够大Netbios就会返回NRCBUFLEN错误ncbcallname指定远程应用的名字ncbname指定应用程序已知的名字ncbrto设定接收操作的超时期限。该值应设为毫秒的一个整数倍数。若为表示没有超时限制。该值是为NCBCALL和NCBLISTEN命令设置的它们会影响后续的NCBRECV命令ncbsto设定发送操作的超时期限。该值应设为毫秒的一个整数倍数。若为表示不存在超时限制。该值是为NCBCALL和NCBLISTEN命令设置的它们会影响后续的NCBSEND和NCBCHAINSEND命令ncbpost指定异步命令完成后需要调用的后例程的地址。函数定义为:voidCALLBACKPostRoutine(PNCBpncb)其中pncb指向已完成命令的网络控制块ncblananum指定要在上面执行命令的LANA编号ncbcmdcpl指定操作的返回代码。异步操作进行期间Netbios会将这个值设为NRCPENDINGncbreserve保留必须为ncbevent指定设置为“未传信”(Nonsignaled)状态的一个Windows事件对象的句柄。完成一个异步命令后事件便会设置成它的“传信”(Signaled)状态。只应使用人工重设事件。假若ncbcommand未设置ASYNCH标志或者ncbpost不为那么该字段必须为。否则Netbios会返回NRCILLCMD错误同步与异步调用Netbios函数时可选择进行同步调用还是进行异步调用。所有NetBIOS命令本身均是同步的。换言之完成命令以前会一直调用Netbios块。而对一个NCBLISTEN命令来说当有一个客户机建立了连接或发生某种类型的错误时对Netbios的调用才会返回。要想异步调用一个命令需要让NetBIOS命令同ASYNCH标志进行一次逻辑OR(或)运算。如指定了ASYNCH标志那么必须在ncbpost字段中指定一个后例程(PostRoutine)或必须在ncbevent字段中指定一个事件句柄。执行一个异步命令时从Netbios返回的值是NRCGOODRET(x)但ncbcmdcplt字段会设为NRCPENDING(xFF)。除此以外Netbios函数还会将NCB结构的ncbcmdcplt字段设为NRCPENDING(待决)直到命令完成为止。命令完成后ncbcmdcplt字段会设为该命令的返回值。Netbios也会在完成后将ncbretcode字段设为命令的返回值。常规NetBIOS例程本节将讨论一个基本的NetBIOS服务器应用程序。之所以首先拿服务器开刀是由于服务器的设计决定了客户机的行为。由于大多数服务器都要求同时为多个客户提供服务所以异步NetBIOS模型是最适合的。展示这个服务器应用程序例子时我们同时用到了异步回调(CallBack)例程以及事件模型。但在我们首先展示的源码中必须实现大多数NetBIOS应用程序、都要用到的一些常规函数。程序清单取自文件Nbcommonc它可在本书配套光盘计计第一部分附传统网络API下载的ExamplesChapterCommon目录下找到。贯穿全书的示范代码都会用到来自本文件的一系列基本函数。程序清单常规NetBIOS例程(Nbcommonc)第章计NetBIOS计计下载计计第一部分附传统网络API下载第章计NetBIOS计计下载计计第一部分附传统网络API下载在Nbcommonc中出现的第一个常规例程是LanaEnum。这是几乎所有NetBIOS应用都会用到的一个最基本的例程。该函数可列举一个指定系统上可用的所有LANA编号。函数会将一个NCB结构初始化成将ncbcommand字段设为NCBENUM为ncbbuffer字段分配一个LANAENUM结构并将ncblength字段设为LANAENUM结构的长度。在NCB结构正确初始化之后为执行NCBENUM命令LanaEnum函数需要采取的唯一行动便是调用Netbios函数。如大家所见一个NetBIOS命令的执行异常简单。对同步命令来说自Netbios返回的值可告诉我们命令是否成功执行。注意常数NRCGOODRET肯定意味着“成功”。使用当前机器上可用的LANA编号数量以及各个实际的LANA编号一次成功的NetBIOS调用会填充完善指定的LANAENUM结构。LANAENUM结构的定义如下:其中length成员指出本地机器共有多少个LANA编号。lana字段代表由实际的LANA编号构成的一个数组。而length值指出lana数组内有多少个元素会被填充LANA编号。接下去的一个函数是ResetAll(全部重设)。同样该函数会在所有NetBIOS应用中用到。对一个编写风格良好的NetBIOS程序来说必须重设计划使用的每个LANA编号。一旦拥有一个LANAENUM结构并有来自LanaEnum的LANA编号便可针对结构中的每个LANA编号调用NCBRESET命令来重设它们。这正是ResetAll要帮我们达到的目的函数的第一个参数是LANAENUM结构。重设只要求函数将ncbcommand设为NCBRESET并将ncblananum设为它需要重设的LANA。注意尽管某些平台(比如Windows)并不要求我们对打算使用的每个LANA编号进行重设但最好还是那样做。WindowsNT要求我们在正式使用前对每个LANA编号进行重设否则对Netbios的其他调用就会返回错误代码(亦即NRCENVNOTDEF)。除此以外重设一个LANA编号时可通过ncbcallname的字符字段设置特定的NetBIOS环境参数。ResetAll的其他参数与这些环境设定是对应的。函数用ucMaxSession参数来设置ncbcallname的字符它用于指定可同时进行的最大会话数量。通常操作系统会强第章计NetBIOS计计下载制使用一个比最大值小的默认值。举个例子来说WindowsNT的最大默认值为个并发会话。ResetAll将ncbcallname的字符(用于指定可为每个LANA增加的最大NetBIOS名字数量)设为ucMaxName参数的值。同样操作系统也会强加一个默认的最大值。最后ResetAll会将字符(用于NetBIOS客户机)设为它的bFirstName参数的值。通过将此参数设为TRUE一个客户机便能将机器名作为自己的NetBIOS进程名使用。因此那个客户机可与一个服务器建立连接并在不允许任何进入连接的前提下向其发送数据。这一选项有效缩短了初始化时间。而假若将一个NetBIOS名字加入本地名字表那么必须为此付出相应的代价。要想将名字加入本地名字表必须用到另一个常规函数:AddName。需要的参数就是想添加的名字以及将其加到哪个LANA编号。请记住每个LANA编号永远对应一个名字表。如果你的应用程序需要与每个可用的LANA通信便需为每个LANA增加进程名。用于增加一个唯一名字的命令是NCBADDNAME。必须使用的其他字段包括要为其增加名字的那个LANA编号以及要实际增加的名字后者必须复制到ncbname中。AddName首先会将ncbname缓冲区初始化成空白然后假定name参数指向一个空中止字串。成功添加一个名字后Netbios会在ncbnum字段中返回同新增名字对应的NetBIOS名字编号。可随数据报一起使用该值以标定始发的NetBIOS进程。有关数据报更深入的情况我们会在本章的后面进行详细讨论。增加一个独一无二的名字时经常遇到的一个错误是NRCDUPNAME。若网络中的另一个进程已使用了要增加的名字便会出现此类错误。AddGroupName的工作原理同AddName大致相同只是它执行的命令是NCBADDGRNAME而且永远不会出现什么NRCDUPNAME错误。DelName是另一个有紧密联系的函数用于从名字表中删除一个NetBIOS名字。它只要求指定打算删除的名字以及从哪个LANA编号上删除那个名字。在程序清单中接下去的两个函数是Send和Recv用于在一个已经建立的会话中进行数据的收发。这两个函数在工作方式上几乎完全相同除了ncbcommand字段的设置以外。这个命令字段可设为NCBSEND或NCBRECV。当然用于收发数据的LANA编号以及相应的会话编号也是必需的参数。若成功执行了一个NCBCALL或NCBLISTEN命令便会返回相应的会话编号。客户机利用NCBCALL命令同一个已知的服务建立连接而服务器使用NCBLISTEN“等候”进入的客户机连接。若两个命令中有一个成功NetBIOS接口便会建立一个会话并为其赋予独一无二的整数标识符。Send和Recv还需要用到映射到ncbbuffer和ncblength的参数。发送数据时ncbbuffer指向那个包含了要送出的数据的缓冲区。在长度(length)字段中指定了缓冲区中应当送出的字符数量。而在接收数据时缓冲区(buffer)字段指向在向其中复制数据的一个内存块。而长度字段指定了该内存块的大小。Netbios函数返回之后它会用成功接收到的字节数来更新长度字段。在一个面向会话的连接中对数据的发送来说要注意的一个重要的问题是在调用Send函数时接收方执行一个Recv函数之前Send函数会一直等待下去。这意味着假如发送方送出大量数据但接收方还没有读取它便会耗用大量本地资源对数据进行缓冲。因此一个良好的编程习惯是同时只执行少数几个NCBSEND或NCBCHAINSEND命令。为进一步解决这个问题请换用Netbios命令NCBSENDNA和NCBCHAINSENDNA命令。通过这两个命令便不必从接收方那里等待收到确认消息而是直接送出数据了事。在程序清单中最后的两个函数是Hangup和Cancel分别用于关闭已经建立的会话计计第一部分附传统网络API下载或者取消一个尚未进行(待决)的命令。我们可调用NetBIOS命令NCBHANGUP来从容关闭一个建好的会话。执行该命令时对于指定的会话来说所有尚未进行的接收调用都会中止并返回一个“会话关闭”错误:NRCSCLOSED(xA)。如果还存在任何没有执行的发送命令则Hangup命令会暂时停止封锁执行等那些命令完成了再说。无论命令正在传输数据还是正在等待远程端执行一个接收命令这种延迟都会发生。会话服务器:异步回调模型现在我们已掌握了进行后续工作所需的基本NetBIOS函数。接下来且让我们看看用于监听“进入”客户机连接的服务器。这只是一个简单的回应反射服务器从客户机那里接收到的任何数据都会立即返还回去。在程序清单中我们展示了具体的服务器代码其中利用的是异步回调函数。在本书配套光盘上亦可找到这个Cbnbsvrc程序位于ExamplesChapterServer文件夹下。注意一下函数main便会发现我们首先用LanaEnum来列举所有可用的LANA编号然后用ResetAll来重设每个LANA。记住在几乎所有NetBIOS应用中都要先采取这两个步骤。程序清单异步回调服务器(Cbnbsvrc)第章计NetBIOS计计下载计计第一部分附传统网络API下载第章计NetBIOS计计下载main接下来要做的事情是将进程名增加到打算用来接收连接的每个LANA编号。通过一次循环服务器会将自己的进程名TESTSERVER增加到每个LANA编号。通过这个名字客户机才能连接我们的服务器(当然要用空格填充)。试图建立或接受一个连接时NetBIOS名字中的每个字符都必须明确指定。对于这个问题大家必须特别留意。编写NetBIOS客户机和服务器代码时最常见的问题便是名字的错误匹配。一定要注意用空格或其他字符来填充名字。空格是最常用的填充字符因为可以列举出来或打印出来总之人眼能够辨别它的存在。对服务器来说最后一个也是最关键的一个步骤是执行大量NCBLISTEN命令。Listen函数首先会分配一个NCB结构。使用异步NetBIOS调用时我们递交的NCB结构必须自执行调用之时开始一直持续到调用结束为止。这便要求我们在执行命令前动态分配每一个NCB结构或者维持一个全局性的NCB结构池以便在异步调用中使用。对NCBLISTEN来说应设置希望通过它进行调用的那个LANA编号。注意在程序清单列出的源代码清单中计计第一部分附传统网络API下载NCBLISTEN命令需要同ASYNCH命令进行逻辑或(OR)运算。指定ASYNCH命令时对ncbpost和ncbevent这两个字段来说其中任意一个必须设为非零值。否则Netbios调用就会出错报告NRCILLCMD(非法命令)错误。在程序清单中Listen函数会将ncbpost字段设成我们的回调函数:ListenCallback。接下来Listen函数将把ncbname字段设为服务器进程的名字。这正是客户机需要与之建立连接的那个名字。函数也会将ncbcallname字段的第一个字符设为一个星号(*)指出服务器可从任何客户机接受连接请求。如果不这样做亦可在ncbcallname字段中设置一个特定的名字只允许注册了那个特定名字的客户机建立与服务器的连接。最后Listen会发出对Netbios的一个调用。调用立即便会完成Netbios函数将已提交的NCB结构的ncbcmdcplt字段设为NRCPENDING(xFF)表示“待决”直到命令执行完毕为止。一旦main完成了重设并为每个LANA编号都投放了一个NCBLISTEN命令主线程会进入一个连续的循环中。注意由于这个服务器仅是一个简单的例子所以在设计上非常简陋。在你编写自己的NetBIOS服务器应用时还可在主循环中进行其他处理或者在主循环中为某个LANA编号投放一个同步NCBLISTEN命令。只有在一个LANA编号上接受了一个进入的连接时回调函数才会执行。NCBLISTEN命令接受了一个连接后会调用由ncbpost指定的函数并将最初的NCB结构作为参数使用。随后ncbretcode会设为返回代码。请务必留意对这个值的检查了解客户机连接是否成功建立。若连接成功会在ncbretcode字段中返回一个NRCGOODRET(x)值。连接成功后需针对同一个LANA编号执行另一个NCBLISTEN命令。之所以要这样做是由于一旦原始的监听操作成功则服务器会停止在那个LANA编号上对客户机的连接进行监听直到递交了另一个NCBLISTEN为止。因此假如服务器需要频繁地为客户提供服务便需在同一个LANA上投放多个NCBLISTEN命令以便能够同时接受多个客户机发出的连接请求。最后回调函数会创建一个特殊的线程为客户机提供服务。在我们的这个例子中线程只是简单地循环并调用一个成块读入命令(NCBRECV)紧接着调用一个成块发送命令(NCBSEND)。所以我们在此实现的是一个简单的回应服务器用于从建立连接的客户机那里读入消息再将其原封不动地“反射”回去。除非客户机中断连接否则客户机线程会一直循环下去。连接中断时客户机线程会执行一个NCBHANGUP命令以便在自己的这一端关闭当前连接。随后客户机线程释放NCB结构占用的空间并正常退出。对面向连接的会话来说数据是由最基层的协议加以缓冲的所以并非一定要发出“待决”的调用。发出一个接收命令后Netbios函数会将可用的数据立即传给现成的缓冲区而且调用会立即返回。而假若没有数据可用接收调用便会暂停直到有数据可用或者会话断开为止。同样的道理也适用于发送命令:若网络堆栈能通过线缆立即送出数据或者能将数据缓存在堆栈中调用便会立即返回。而假若系统没有足够的缓冲区空间来立即送出数据发送调用便会暂停直到有可用的空间为止。要想避免这种形式的数据延误可对数据的收发使用ASYNCH(异步)命令。若执行的是异步发送或接收命令那么相应的缓冲区必须有一个较大的容量超出调用进程本身的范围之外。避免收发延误的另一个办法是使用ncbsto和ncbrto这两个字段。其中ncbsto字段用于设置发送延时。若为其指定一个非零值便相当于为命令的执行规定了一个超时时限。注意时间长度是以毫秒为单位指定的。如命令超第章计NetBIOS计计下载时便需要立即返回数

用户评价(1)

  • 冰冰 书名写错了吧,是windows网络编程技术, 不要误导读者

    2012-02-16 01:34:01

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/49

【No

仅供在线阅读

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利