下载第 6章 地址家族和名字解析要通过 Wi n s o c k建立通信,必须了解如何利用指定的协议为工作站定址。本章将一一说明
Wi n s o c k支持的协议以及各协议如何把一个指定家族的地址解析成网络上一台具体的机器。
Winsock 2引入了几个新的、与协议无关的函数,它们可和任何一个地址家族一起使用;但是大多数情况下,各协议家族都有自己的地址解析机制,要么通过一个函数,要么作为一个投给 g e t s o c k o p t的选项。本章只讲解各协议组成地址结构时所需的一些基本知识。第 1 0章讨论注册和名字解析函数,这些函数对特定协议家族服务进行声明(这和简单的名字解析稍有不同) 。
关于直接名字解析、服务声明与解析之间的差别,可参见第 1 0章。
对已讲过的地址家族来说,我们将进一步探讨如何为网络上的一台机器定址。然后,再针对各个家族建立套接字。除此以外,还要讨论协议独有的名字解析选项。
6.1 IP
网际协议( Internet Protocol,IP)是一种用于互联网的网络协议,已经广为人知。它可广泛用于大多数计算机操作系统上,也可用于大多数局域网 L A N(比如办公室小型网络)和广域网 WA N(比如说互联网) 。从它的设计看来,I P是一个无连接的协议,不能保证数据投递万无一失。两个比它高级的协议( T C P和 U D P)用于依赖 I P协议的数据通信。
6.1.1 TCP
面向连接的通信是通过“传输控制协议” ( Transmission Control Protocol,TCP)来完成的。
T C P提供两台计算机之间的可靠无错的数据传输。应用程序利用 T C P进行通信时,源和目标之间会建立一个虚拟连接。这个连接一旦建立,两台计算机之间就可以把数据当作一个双向字节流进行交换。
6.1.2 UDP
无连接通信是通过“用户数据报协议” ( User Datagram Protocol,UDP)来完成的。 U D P
不保障可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。简单地说,如果一个客户机向服务器发送数据,这一数据会立即发出,不管服务器是否已准备接收数据。如果服务器收到了客户机的数据,它不会确认收到与否。数据传输方法采用的是数据报。
T C P和 U D P两者都利用 I P来进行数据传输,一般称为 T C P / I P和 U D P / I P。 Wi n s o c k通过
A F _ I N E T地址家族为 I P通信定址,这个地址家族的定义在 Winsock 1.h和 Winsock 2.h中。
6.1.3 定址
I P中,计算机都分配有一个 I P地址,用一个 3 2位数来表示,正式的称呼是,I P v 4地址” 。
客户机需要通过 T C P或 U D P和服务器通信时,必须指定服务器的 I P地址和服务端口号。另外,
第 6章 计 地址家族和名字解析 计计 103下载服务器打算监听接入客户机请求时,也必须指定一个 I P地址和一个端口号。 Wi n s o c k中,应用通过 S O C K A D D R _ I N结构来指定 I P地址和服务端口信息,该结构的格式如下:
s i n _ f a m i l y字段必须设为 A F _ I N E T,以告知 Wi n s o c k我们此时正在使用 I P地址家族。
IP协议第 6版
I P协议第 6版对原来的 I P协议规格进行了改进,将 I P地址扩展到 1 6个字节。随着 I P v 4
的退场,不久的将来,I P v 6的地位显得越来越重要。许多 Wi n s o c k头文件中都包含针对
I P v 6结构的条件定义;但是当前的 Wi n 3 2平台均没有提供 I P v 6网络堆栈(包括 Wi n d o w s
2 0 0 0在内) 。,微软研究部”已开发出一个试验性的 I P v 6堆栈,可从 h t t p,/ / r e s e a r c h,
m i c r o s o f t,c o m / m s t r i p v 6 /下载;然而,该堆栈未获支持,而且我们不打算深入第 6版协议中专有的特性。
准备使用哪个 T C P或 U D P通信端口来标识服务器服务这一问题,则由 s i n _ p o r t字段定义。
在选择端口时,应用必须特别小心,因为有些可用端口号是为“已知的” (即固定的)服务保留的(比如说文件传输协议和超文本传输协议,即 F T P和 H T T P) 。,已知的协议”,即固定协议,采用的端口由“互联网编号分配认证( I A N A),控制和分配,RFC 1700中说明编号。从本质上说,端口号分为下面这三类:,已知”端口、已注册端口、动态和(或)私用端口。
■ 0 ~ 1 0 2 3由 I A N A控制,是为固定服务保留的。
■ 1 0 2 4 ~ 4 9 1 5 1是 I A N A列出来的、已注册的端口,供普通用户的普通用户进程或程序使用。
■ 4 9 1 5 2 ~ 6 5 5 3 5是动态和(或)私用端口。
普通用户应用应该选择 1 0 2 4 ~ 4 9 1 5 1之间的已注册端口,从而避免端口号已被另一个应用或系统服务所用。此外,4 9 1 5 2 ~ 6 5 5 3 5之间的端口可自由使用,因为 I A N A这些端口上没有注册服务。在使用 bind API函数时,如果一个应用和主机上的另一个应用采用的端口号绑定在一起,系统就会返回 Wi n s o c k错误 W S A E A D D R I N U S E。第 7章将深入阐述 Wi n s o c k绑定进程。
S O C K A D D R _ I N结构的 s i n _ a d d r字段用于把一个 I P地址保存为一个 4字节的数,它是无符号长整数类型。根据这个字段的不同用法,还可表示一个本地或远程 I P地址。 I P地址一般是用“互联网标准点分表示法” (像 a,b,c,d一样)指定的,每个字母代表一个字节数,从左到右分配一个 4字节的无符号长整数。最后一个字段 sin_ zero,只充当填充项的职责,以使
S O C K A D D R _ I N结构和 S O C K A D D R结构的长度一样。
一个有用的、名为 i n e t _ a d d r的支持函数,可把一个点式 I P地址转换成一个 3 2位的无符号长整数。它的定义如下:
unsigned long inet_addr(
const char FAR *cp
);
c p字段是一个空中止字符串,它认可点式表示法的 I P地址。注意,这个函数把 I P地址当作一个按网络字节顺序排列的 3 2位无符号长整数返回(网络字节顺序在下面的“字节排序”小节中简要说明) 。
1,特殊地址对于特定情况下的套接字行为,有两个特殊 I P地址可对它们产生影响。特殊地址
I N A D D R _ A N Y允许服务器应用监听主机计算机上面每个网络接口上的客户机活动。一般情况下,在该地址绑定套接字和本地接口时,网络应用才利用这个地址来监听连接。如果你有一个多址系统,这个地址就允许一个独立应用接受发自多个接口的回应。
特殊地址 I N A D D R _ B R O A D C A S T用于在一个 I P网络中发送广播 U D P数据报。要使用这个特殊地址,需要应用设置套接字选项 S O _ B R O A D C A S T。第 9章将对该选项进行详细论述。
2,字节排序针对“大头” ( b i g - e n d i a n)和“小头” ( l i t t l e - e n d i a n)形式的编号,不同的计算机处理器的表示方法有所不同,这由各自的设计决定。比如,Intel 86处理器上,用“小头”形式来表示多字节编号:字节的排序是从最无意义的字节到最有意义的字节。在计算机中把 I P地址和端口号指定成多字节数时,这个数就按“主机字节” ( h o s t - b y t e)顺序来表示。但是,如果在网络上指定 I P地址和端口号,“互联网联网标准”指定多字节值必须用“大头”形式来表示
(从最有意义的字节到最无意义的字节),一般称之为“网络字节” ( n e t w o r k - b y t e)顺序。
有一系列的函数可用于多字节数的转换,把它们从主机字节顺序转换成网络字节顺序,
反之亦然。下面四个 A P I函数便将一个数从主机字节顺序转换成网络字节顺序:
h t o n l和 W S A H t o n l的 h o s t l o n g参数是按主机字节顺序的一个 4字节数。 h t o n l函数返回的数顺序是网络字节顺序,而 W S A H t o n l函数通过 l p n e t l o n g参数返回的数顺序是网络字节顺序。
h t o n s和 W S A H t o n s的 h o s t s h o r t参数是按主机字节顺序的一个 2字节数。 h t o n s函数把这个数当作按网络字节顺序的一个 2字节值返回,而 W S A H t o n s函数通过 l p n e t s h o r t参数把这个数返回。
下面这四个是前面四个函数的反向函数:它们把网络字节顺序转换成主机字节顺序:
104计计 第二部分 附 Winsock API 下载现在,我们打算演示一下如何利用上面描述的 i n e t _ a d d r 和 h t o n s 函数来创建
S O C K A D D R _ I N结构。
6.1.4 创建套接字创建一个 I P套接字的好处是便于应用能够通过 T C P,U D P和 I P协议进行通信。如要用 T C P
协议打开一个 I P套接字,需调用带有地址家族 A F _ I N E T和套接字类型 S O C K _ S T R E A M的
s o c k e t函数或 W S A S o c k e t函数,并把协议字段设成 0,方式如下:
要利用 U D P协议打开 I P套接字,只须指定套接字类型,用这个指定的套接字类型代替
s o c k e t函数中的 S O C K _ S T R E A M和上面的 W S A S o c k e t调用。还可以打开一个套接字通过 I P直接通信。这是把套接字类型设成 S O C K _ R AW来完成的。第 1 3章将对 S O C K _ R AW选项进行深入探讨。
6.1.5 名字解析
Wi n s o c k应用打算通过 I P和主机通信时,必须知道这个主机的 I P地址。依用户看来,I P地址是不容易记的。在指定机器时,许多人更愿意利用一个易记的、友好的主机名而不是 I P地址。 Wi n s o c k提供了两个支持函数,它们有助于用户把一个主机名解析成 I P地址。
Wi n d o w s套接字 g e t h o s t b y n a m e和 WSAAsynGetHostByName API函数从主机数据库中取回与指定的主机名对应的主机信息。两个函数均返回一个 H O S T E N T结构,该结构的格式如下:
第 6章 计 地址家族和名字解析 计计 105下载
h _ n a m e字段是正式的主机名。如果网络采用了“域内命名系统” ( D N S),它就是导致命名服务器返回响应的“全限定域名” ( F Q D N) 。如果网络使用一个本地“多主机”文件,主机名就是 I P地址之后的第一个条目。 h _ a l i a s e s字段是一个由主机备用名组成的空中止数组。
h _ a d d r t y p e表示即将返回的地址家族。 h _ l e n g t h字段则对 h _ a d d r _ l i s t字段中的每一个地址定义字节长度进行定义。 h _ a d d r _ l i s t字段是一个由主机 I P地址组成的空中止数组(可以为一个主机分配若干个 I P地址) 。这个数组中的每个地址都是按网络字节顺序返回的。一般情况下,应用程序都采用该数组中的第一个地址。但是,如果返回的地址不止一个,应用程序就会相应地选择一个最恰当的,而不是一直都用第一个地址。
gethostbyname API函数的定义如下:
n a m e参数表示准备查找的那个主机的友好名。如果这个函数调用成功,系统就会返回一个指向 H O S T E N T结构的指针。注意,保存 H O S T E N T结构的是系统内存。应用程序不应该依靠它来维护状态。由于该内存由系统维护,因此,你的应用程序不必释放这个已返回的结构。
WSAAsyncGetHostByName API函数是 g e t h o s t b y n a m e函数的异步版,后一个函数在结束时,利用 Wi n d o w s消息向应用程序发出通知。 W S A A s y n G e t H o s t B y N a m e的定义如下:
b W n d参数是窗口句柄,异步请求结束时,这个句柄将收到一条消息。 w M s g参数是异步请求结束时收到的窗口消息。 n a m e参数代表我们正在查找的主机之用户友好名。 b u f参数是一个指针,它指向接收 H O S T E N T数据的那个数据域。这个缓冲区必须大于 H O S T E N T结构,应该设为 M A X G E T H O S T S T R U C T中定义的最大长度。
另外两个用于获得主机信息的函数是,g e t h o s t b y a d d r和 WSAAsynGetHostByName API函数,它们是为获得与 I P网络地址相应的主机信息而设计的。在有了主机 I P地址,并打算查找其用户友好名时,这两个函数非常有用。 g e t h o s t b y a d d r函数的定义如下:
a d d r参数是指向一个 I P地址的指针,这个地址按网络字节顺序排列。 l e n参数用于指定 a d d r
参数的字节长度。 t y p e 参数将指定 A F _ I N E T 值,这个值表明指定类型是 I P地址。
WSAAsyncGetHostByAddr API函数是 g e t h o s t b y a d d r函数的异步版。
端口号
106计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 107下载应用打算与运行于本地或远程计算机上的服务进行通信时,除了要知道远程计算机的 I P
地址外,还必须知道服务的端口号。在使用 T C P和 U D P时,应用必须决定计划通过哪些端口进行通信。有几个“已知的端口号”是服务器服务保留的,这些服务支持比 T C P高级的协议
(比如 T C P和 S P X) 。举个例子来说,端口 2 1是为 F T P预留的,端口 8 0是为 F T T P预留的。正如前面提到的那样,已知的服务一般都采用 1 ~ 1 0 2 3之间的端口号来设置协议。如果你正在开发一个不使用任何一种已知服务的 T C P应用,就要考虑采用 1 0 2 3以上的端口,以免重复。通过调用 g e t s e r v b y n a m e和 W S A A s y n c G e t S e r v B y N a m e函数,便可获得已知服务的端口号。这两个函数只从名为 s e r v i c e s的文件中获得静态信息。 Windows 95和 Windows 98中,服务文件位于
% W I N D O W S%下面;在 Windows NT 和 Windows 2000中,则位于% W I N D O W S%
\ S y s t e m 3 2 \ D r i v e r s \ E t c下面。 g e t s e r v b y n a m e函数的定义如下:
n a m e参数代表准备查找的服务名。举个例子来说,如果你正在定位 F T P端口,就应该把
n a m e参数设成指向字串,f t p” 。 p r o t o参数随便指向一个字串,这个字串表明 n a m e中的服务是在这个参数中的协议下面注册的。 W S A A s y n c G e t S e r v B y N a m e函数是 g e t s e r v b y n a m e函数的异步版。
Windows 2000中有一个新的注册和请求 T C P及 U D P服务信息的动态方法。服务器应用可利用 W S A S e t S e r v i c e函数来注册服务名,I P地址和服务的端口号。客户机应用可利用这三个 A P I
函数的组合请求这条服务信息,这三个函数是 W S A L o o k u p S e r v i c e B e g i n,W S A L o o k u p S e r v i c e N e x t
和 W S A L o o k u p S e r v i c e E n d。第 1 0章将对此进行讨论。
6.2 红外线套接字红外线套接字称为 I r S o c k,它是一个令人兴奋不已的新技术,首先在 Wi n d o w s平台上亮相。
红外线套接字允许两台计算机通过红外线串行端口进行通信。目前,红外线套接字可在
Windows 98和 Windows 2000上使用。红外线套接字不同于传统意义上针对便携机的短暂性而设计的套接字。它们展示了一种新的名字解析模型,下一小节中将对此进行讨论。
6.2.1 定址由于带有“红外线数据联盟” ( Infrared Data Association,IrDA)设备的大多数计算机可能经常性地拆卸,传统的名字解析方案不能满足人们的需求。传统解析方法充当命名服务器之类的静态资源 — 人们在移动正在运行网络客户任务的手提式电脑或膝上型计算机时,是不能使用这些资源的。为解决这一问题,I r D A就设计成了这样:无须在整个大型网络上,只须用一种特定的方式浏览范围内的资源,因此,I r D A没有使用标准的 Wi n s o c k命名服务函数和
I P定址。相反,命名服务已并入通信流,另外还引入了一个新的地址家族,以支持与红外线串行端口绑定在一起的服务。 I r S o c k地址结构中包含一个服务名(它对绑定和连接调用中所使用的应用进行描述)和一个设备标识符(描述运行服务的设备) 。这里的服务名和设备标识符类似于传统 T C P / I P套接字所用的 I P地址和端口号字元组。 I r S o c k地址结构的定义如下:
i r d a A d d r e s s F a m i l y字段一直都是 A F _ I R D A。 i r d a D e v i c e I D是一个 4字符的字串,用于唯一性地标识特定服务所运行的设备。在建立 I r S o c k服务器时,这个字段是忽略不计的。但是对客户机而言,却非常重要,因为它指定的是准备连接的那个 I r D A设备(也可能有若干个) 。最后,
i r d a S e r v i c e N a m e字段是服务名,应用要么利用这项服务对其本身进行注册,要么试着与这项服务建立连接。
6.2.2 名字解析定址可以利用,I r D A逻辑服务访问点选择符( L S A P - S E L),或“信息访问服务” ( I A S)
注册的服务为基础。 I A S从一个 L S A P - S E L中摘出一项服务,并把它置入用户友好的文本服务名中,方式和互联网域名服务器把名字映射到数字化 I P地址差不多。要成功建立一个连接,
既可以用 L S A P - S E L,又可以用用户友好名。不过,用户友好名需要名字解析。大多数时候,
都不要使用直接的 L S A P - S E L“地址”,因为 I r D A服务的地址空间是限制了的。 Wi n 3 2实施方案允许 L S A P - S E L整数标识符,标识符的范围是 1到 1 2 7。从本质上说,我们可把 I A S服务器当作一个 W I N S服务器,因为它把 L S A P - S E L和一个文字化的服务名关联在一起。
事实上的 I A S条目有三个重要字段:类名、属性和属性值。举个例子来说,一个服务器希望在服务名 M y S e r v e r下对其本身进行注册。这是服务器通过相应的 S O C K A D D R _ I R D A结构执行绑定调用时完成的。这种情况一旦发生,就会增加一个 I A S条目,该条目中包括类名
M y S e r v e r、属性 I r D A,Ti n y T P,L s a p - S E L和属性值 3。属性值就是下一个未用过的 L S A P - S E L,
这个 L S A P - S E L 是系统根据注册来分配的。另一方面,客户机向连接调用投递一个
S O C K A D D R _ I R D A 结构。随后便开始 I A S 查找,查找带有类名 M y S e r v e r 和属性
I r D A,Ti n y T P,L s a p - S E L的那项服务。 I A S查询会返回 3这个值。用户可利用 g e t s o c k e t o p t调用中的套接字选项 I R L M P _ I A S _ Q U E RY来定制自己的 I A S查询。
如果打算完全忽略 I A S(一般不建议使用),则可为客户机准备连接的服务名或终端直接指定一个 L A S P - S E L地址。忽略 I A S后,就只能和不提供任何 I A S注册的老 I r D A设备(比如红外线打印机)进行通信。把 S O C K A D D R _ I R D A结构中的服务名指定为 L S A P - S E L - x x x,就可忽略 I A S注册和查找。其中,x x x处是属性值,其范围在 1到 1 2 7之间。对服务器而言,这样会直接为该服务器分配特定的 L S A P - S E L地址(假定这个 L S A P - S E L地址尚未使用) 。对客户机而言,这样会忽略 I A S查找,并试图马上与运行于指定的 L S A P - S E L上的任何一项服务建立连接。
6.2.3 红外线设备列举由于红外线设备的使用地点不固定,因此,必须有一种方法,可以动态地把特定范围内的所有可用红外线设备列举出来。我们先从 Windows CE实施方案和 Windows 98及 Wi n d o w s
2 0 0 0实施方案之间的几点差别谈起。 Windows CE先于其他平台支持 I r S o c k,并提供少量与红外线设备有关的信息。后来,Windows 98和 Windows 2000也开始支持 I r S o c k,但它们新增了另外的“提示”信息,该信息是由列举请求返回的(关于提示信息,我们稍后将简要论述) 。
108计计 第二部分 附 Winsock API 下载这样一来,Windows CE的 A F _ i r d a,h头文件中包含的是原始的、少量的结构定义;但是,其他平台提供的新的头文件中包含的则是目前支持 I r S o c k的各个平台的条件结构定义。为了保持一致,我们建议大家采用较新的 A f _ i r d a,h头文件。
列举临近红外线设备的方法是采用 g e t s o c k o p t的 I R L M P _ E N U M _ D E V I C E命令。
D E V I C E L I S T结构被当作 o p t v a l参数投递。这里有两个结构,一个针对 Windows 98和 Wi n d o w s
2 0 0 0,另一个针对 Windows CE。这两个结构的格式如下:
Windows 98和 Windows 2000结构与 Windows CE结构之间的唯一区别是 Windows 98和
Windows 2000结构中包含一个 W I N D O W S _ I R D A _ D E V I C E _ I N F O数组,该数组与 W C E _
I R D A _ D E V I C E _ I N F O结构的数组相对应。条件性的 # d e f i n e指令根据目标平台,声明
D E V I C E L I S T结构是正确的。同样,也有对 I R D A _ D E V I C E _ I N F O结构的两个声明:
# d e f i n e指令根据目标平台,向正确的结构定义声明 I R D A _ D E V I C E _ I N F O。
正如前面提到的那样,真正用于列举红外线设备的函数是带有 I R L M P _ E N U M _ D E V I C E S
选项的 g e t s o c k o p t函数。下面这一段代码,可把邻近的所有红外线设备 I D列举出来:
第 6章 计 地址家族和名字解析 计计 109下载在向 g e t s o c k o p t调用投递一个 D E V I C E L I S T结构之前,别忘了把 n u m D e v i c e字段设成 0。一次成功列举会把 n u m D e v i c e字段设成一个大于 0的值,并把 D e v i c e字段中 I R D A _ D E V I C E _ I N F O
结构数量设为前一个值。同时,在实际应用中,为检查新使用的设备,可能会多次执行
g e t s o c k o p t。举个例子来说,一个很好的例子就是试着进行五次或少于五次的红外线设备查找。
方法很简单:在未成功列举之后,利用短期调用 S l e e p,把该调用置入循环即可。
现在,大家已知道如何列举红外线设备,创建一个客户机或服务器就更简单了。同级的服务器端更为简单,因为它像一个“普通”服务器。也就是说,不需要额外的步骤。创建
I r S o c k服务器的常见步骤如下;
1) 建立一个地址家族 A F _ I R D A套接字和套接字类型 S O C K _ S T R E A M。
2) 用服务器的服务名填写一个 S O C K A D D R _ I R D A结构。
3) 利用套接字句柄和 S O C K A D D R _ I R D A结构调用 b i n d。
4) 利用套接字句柄和 b a c k l o g边限调用 l i s t e n。
5) 为接入客户机锁定一个 a c c e p t调用。
建立客户机的步骤稍微有些复杂,因为必须先把红外线设备列举出来。建立 I r S o c k客户机所需步骤如下:
1) 建立地址家族 A F _ I R D A套接字和套接字类型 S O C K - S T R E A M。
2) 调用有 I R L M P _ E N U M _ D E V I C E S选项的 g e t s o c k o p t函数,列举所有可用的红外线设备。
3) 针对返回的每个设备,利用设备 I D和准备连接的服务名填写一个 SOCKADDR_ IRDA
结构。
4) 利用套接字句柄和 S O C K A D D R _ I R D A结构,调用 c o n n e c t函数。针对步骤 3)中所填的结构,重复步骤 4),直到连接成功。
6.2.4 查询 IAS
要知道特定服务是否在特定的设备上运行,有两种方法。第一种是真正与特定服务连接;另一种是向 I A S查询特定的服务名。两种方法都要求列举红外线设备,然后对每一个设备进行查询直到达到目的或所有的设备都查完。执行查找是调用带有 I R L M P _ I A S _ Q U E RY选项的 g e t s o c k o p t函数来完成的。再次提醒大家注意,I A S _ Q U E RY结构有两个,一个针对
Windows 98和 Windows 2000,另一个针对 Windows CE。各结构的格式如下:
110计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 111下载大家可看到,除了特定字符数组的长度不同之外,这两个结构的格式是差不多的。
要对特定服务的 L S A P - S E L数有多少进行查询,很简单:把 i r d a C l a s s N a m e字段设为 L S A P -
S E L的属性字串,即 I r D A,I r L M P,L s a p S e l,然后,把 i r d a A t t r i b u t e N a m e字段设成准备查询的那个服务名。除此以外,还必须用范围内的有效设备来设置 i r d a D e v i c e I D字段。
6.2.5 创建套接字红外线套接字的创建很简单。几乎不需要任何选项,这是因为 I r S o c k只支持面向连接的数据流。下面的代码说明了如何利用 s o c k e t或 W S A S o c k e t调用来建立红外线套接字。由于
Winsock 1.1的限制,必须采用 Windows CE的 s o c k e t。
如果不想因循守旧,可把 I R D A _ P R O TO _ S I C K _ S T R E A M当作上面任何一个函数的协议参数投递出去。但系统不需要这个协议参数,因为传输目录中只有一个地址家族 A F _ I R D A条目。
指定 A F _ I R D A会造成默认使用这个传输条目。
6.2.6 套接字选项对 I r D A来说,大多数 S O _ s o c k e t选项都是没有意义的,只有 S O _ L I N G E R得到了特别的支持。 I r S o c k特有的套接字选项当然也得到了支持,不过只限于地址家族 A F _ I R D A套接字上。
我们将在第 9章全面论述这些选项,第 9章还对所有套接字选项及其参数进行了总结。
6.3 IPX/SPX
“互联网包交换” ( I P X)协议是一个常见协议,一般为承担 Novell NetWa r e客户机/服务器联网服务的计算机所用。 I P X提供两个进程间的无连接通信;因此,如果一个工作站发出一个数据包,该协议无法保证这个数据包会准确无误地投递到目标地点。如果应用程序需要数据投递保证,但仍坚持使用 I P X,它就会选用一个比 I P X高级的协议,比如说“顺序分组交换”
( S P X)和 SPX II协议,这两个协议中,S P X包通过 I P X发送。 Wi n s o c k为应用程序提供了在
Wi n d o w s平台上通过 I P X进行通信的能力(它们是 Windows 95,Windows 98,Windows NT以及 Windows 2000),但没有提供 Windows CE平台上通过 I P X通信的能力。
6.3.1 编址
I P X网络、网段是用 I P X路由器桥接在一起的。每个网段分配 4字节的唯一地址号。当更多的网段桥接在一起时,I P X路由器管理网段之间的通信,每个网段有唯一的网段号。连网时,
使用唯一的 6字节网段号,这个号也往往是转接器的物理地址。一个节点(也就是一台计算机)
一般有一个或多个通信进程用 I P X通信。 I P X用套接字号来区分一个节点上的通信。
要用 I P X进行 Wi n s o c k客户机或服务器通信,必须建立 S O C K A D D R _ I P X结构。该结构在
W s i p x,h头文件中定义,应用程序在包括 Winsock 2.h文件之后还必须包括该文件。 S O C K A D D R _
I P X结构如下定义:
s a _ f a m i l y字段应设为 A F _ I P X值,s a _ n e t n u m字段是 4字节的地址,代表 I P X网络上网段号,
s a _ n o d e n u m字段是 6字节的地址,代表节点计算机的物理地址,s a _ s o c k e t字段代表一个节点区分 I P X通信的套接字或接口。
6.3.2 创建套接字利用 I P X创建套接字提供了几种可能性。要打开 I P X套接字,调用带有地址家族 A F _ I P X、
套接字类型以及 N S P R O TO _ I P X协议的 s o c k e t函数或 W S A S o c k e t函数即可,过程如下:
112计计 第二部分 附 Winsock API 下载注意,第三个参数协议是必须指定的,而且不能为 0。这一点相当重要,因为该字段还可用于设置特定 I P X包的类型。
正如我们前面提到的那样,I P X利用数据报提供不可靠的无连接通信。如果一个应用需要可靠的无连接通信,可采用比 I P X高级的协议,比说 S P X和 SPX II。要做到这一点,把 s o c k e t
和 W S A S o c k e t调用的类型和协议字段分别设置成套接字类型 S O C K _ S E Q PA C K E T或
S O C K _ S T R E A M和协议字段 N S P R O TO _ S P X或 N S P R O TO_SPX II即可。
如果指定了 S O C K _ S T R E A M,系统就会把数据当作连续不断的字节流发送出去,没有消息边界,这类似于 T C P / I P中套接字的行为。另一方面,如果发送端发出 2 0 0 0个字节,在这
2 0 0 0个字节全部到达接收端之前,接收端是不会返回任何消息的。对 S P X和 SPX II来说,这是通过设置 S P X头中的消息结束位来完成的。指定 SOCK_ STREAM时,要注意这个位,
Winsock recv和 W S A R e c v调用在其收到这个位之前不会中止。如果指定 S O C K _ S T R E A M时没有注意到这个消息结束位,一旦接收端收到数据,r e c v就会中止,不管消息结束位设在哪里。
从发送端这一方来说(使用 S O C K _ S E Q PA C K E T类型),如果发送的数据包小于一个完整的数据包,消息结束位就会随这个包一起发送。如果发送的包大于一个完整的数据包,消息结束位就只设在最后发送的那个包中,而不是每个包都有。
1,绑定套接字
I P X应用通过 b i n d把本地地址和套接字关联在一起时,不要在 S O C K A D D R _ I P X结构中指定网络号和节点地址。 b i n d函数利用系统上可用的第一个 I P X网络接口来填充这些字段。如果一台计算机有多个网络接口(多址计算机),它就不必绑定特定的接口。 Windows 95、
Windows 98,Windows NT和 Windows 2000提供一个虚拟内部网,不管它直接连接的物理网络如何,该虚拟网中的每个接口都是可以抵达的。我们稍后将对内部网络编号进行详细论述。
应用成功绑定本地接口之后,便可利用下属代码段中的 g e t s o c k n a m e函数获得本地网络编号和节点编号的信息。
第 6章 计 地址家族和名字解析 计计 113下载
114计计 第二部分 附 Winsock API 下载
2,网络编号与内部网络编号网络编号(通常称作外部网络编号)用于标识 I P X中的网络段和 I P X报在网络段之间的路由选择。 Windows 95,Windows 98,Windows NT以及 Windows 2000平台特别突出了内部网络编号,这个内部网络编号用于内部路由选择和对网间网(几个网络桥接在一起构成)上的计算机进行唯一性标识。内部网络编号也称为“虚拟网号”,即内部网络编号对网间网中的另一个(虚拟的)网络段进行标识。因此,如果一台计算机正在运行 Windows 95,Windows 98、
Windows NT或 Windows 2000,若打算为它配置一个内部网络编号,N e t Wa r e服务器或 I P X路由器就会在自己与那台计算机的路由之间另增一次跳跃。
在多址计算机情形下,内部虚拟网络用于某一特定目的。应用程序绑定本地网络接口时,不应该指定本地接口信息,但需要把 S O C K A D D R _ I P X结构的 s a _ n e t n u m和 s a _ n o d e n u m这两个字段设置为 0。这是因为 I P X能够通过内部虚拟网络的使用,把一个数据包从任何一个外部网络路由到任何一个本地网络接口。比如,即使你的应用程序明显地绑定网络 A上的网络接口,而数据包却来自网络 B,内部网络编号就会使这个数据包在内部路由,这样,你的应用程序就收到这个数据包了。
3,通过 Wi n s o c k,设置 I P X数据包的类型在利用 N S P R O TO _ I P X建立套接字时,Wi n s o c k允许应用程序指定 I P X包的类型。 I P X包内的数据包类型字段表明这个 I P X包提供或请求的服务类型。在 N o v e l l网中,下面的 I P X包类型的定义是:
■ 0 1 h:路由信息协议( R I P)包。
■ 0 4 h:服务声明协议( S A P)包。
■ 0 5 h:顺序分组交换( S P X)包。
■ 11 h,N e t Ware Core协议( N C P)包。
■ 1 4 h,Novell NetBIOS的传输包。
要修改 I P X包类型,只须把 N S P R O TO_IPX + N指定为 socket API的协议参数,n表示数据包类型的编号。比如,要打开一个把包类型设为 0 4 h( S A P包)的 I P X套接字,可用下面的
s o c k e t调用:
4,名字解析大家可能知道,Wi n s o c k中的 I P X定址有些麻烦,因为必须提供构成地址的多字节的网络和节点编号。 I P X使应用程序可以通过用户友好名找到相应服务,以此通过 S A P协议获得 I P X
网络中的网络编号、节点编号和端口编号。正如我们将在第 1 0章看到的那样,Winsock 2利用
WSASetService API函数,提供了一个与协议无关的名字解析法。通过 S A P协议,I P X服务器应用可利用 W S A A e t S e r v i c e在用户友好名下注册它们正在监听的网络编号、节点编号和端口第 6章 计 地址家族和名字解析 计计 115下载编号。 Winsock 2还通过下面几个 A P I函数提供了另一个与协议无关的名字解析法,它们是:
W S A L o o k u p S e r v i c e B e g i n,W S A l o o k u p S e r v i c e N e x t和 W S A l o o k u p S e r v i c e E n d。
要执行自己的命名服务注册和查找,可以通过打开一个 I P X套接字并指定 S A P类型的方法来完成。打开套接字之后,便可开始向 I P X网络广播 S A P包,以便在网络上注册和定位服务。
这要求大家深入了解 S A P协议和掌握针对 IPX SAP包解码的编程方面的基本知识。
6.4 NetBIOS
N e t B I O S地址家族也是另一种可从 Wi n s o c k访问的协议家族。通过第 1章的 N e t B I O S讨论,
大家将进一步熟悉这里提到的许多主题和注意事项。从 Wi n s o c k开始的 N e t B I O S定址仍需要得知 N e t B I O S名和 L A N A编号。我们假定大家已看过第 1章中的这些小节,然后,继续深入通过
Wi n s o c k访问 N e t B I O S的特性。
注意 NetBIOS地址家族由 Winsock剖析,只能用于 Windows NT和 Windows 2000。不能用于 Windows 95,Windows 98和 Windows CE。
6.4.1 定址
N e t B I O S下机器的定址基础是 N e t B I O S名,这个我们已在第 1章中讲过。 N e t B I O S名有 1 6
个字符长,最后一个字符留给定义这个名属于哪类服务的限定字符用。 N e t B I O S名有两种类型:专有名和组名。专有名可只由整个网络上的一个进程注册。比如,一个基于会话的服务器将注册 F O O名,而打算和该服务器沟通的客户机则试着和 F O O连接。组名允许一组应用注册同一个名字,如此一来,注册了这个组名的所有进程都可收到发给这个名字的数据报。
Wi n s o c k中,N e t B I O S定址结构是在 W s a n e t b s,h中定义的,格式如下:
s n b _ f a m i l y字段指定这个结构的地址家族,它应该始终为 A F _ N E T B I O S。 s n b _ t y p e字段用于指定一个专有名或组名。下面的定义可用于这个 s n b _ t y p e字段:
最后,s n b _ n a m e字段就是事实上的 N e t B I O S名。
现在,大家已知道各字段的含义以及应该怎样设置它们了,下面设置的宏定义于头文件中,方便易行:
这个宏的第一个参数 _ s n b是此时正在填的 S O C K A D D R _ N B结构的地址。正如大家所见的那样,它自动把 s n b _ f a m i l y字段设为 A F _ N E T B I O S。而这个宏的 _ t y p e参数指定的是
N E T B I O S _ U N I Q U E _ N A M E或 N E T B I O S _ G R O U P _ N A M E。 _ n a m e参数是 N e t B I O S名。这个宏认定其长度至少是 N E T B I O S _ N A M E _ L E N G T H减 1,如果短于这一长度,它就会空中止。注意,s n b _ n a m e字段是用空格来预填的。最后,这个宏把 s n b _ n a m e字符串的第 1 6个字符设为
_ p o r t参数的值。
大家可看到,Wi n s o c k中 N e t B I O S名的结构是直接了当的,没有任何令人费解之处。名字解析是在悄然执行的,因此,它不像 T C P和 I r D A那样,在执行操作之前,不必把名字解析成物理地址。在考虑到依赖于多个协议实施 N e t B I O S,但各个协议都有自己的一套定址方案时,
这一点更为明显。下一章中,我们将通过在 Wi n s o c k中使用 N e t B I O S接口,向大家展示一个简单的客户机/服务器范例。
6.4.2 创建套接字创建套接字时,最重要的一点是 L A N A编号。就像使用原始 NetBIOS API那样,必须知道哪些 L A N A编号和你的应用有关。必须记住,N e t B I O S客户机和服务器要进行通信,必须有一个常用的传输协议,这样它们便可通过该协议进行监听或连接。创建 N e t B I O S套接字有两种方法。其一是像下面这样调用 s o c k e t或 W S A S o c k e t:
根据你需要的是一个无连接数据报,还是面向连接的会话套接字,W S A S o c k e t的 t y p e参数分别是 S O C K _ D G R A M和 S O C K _ S E Q PA C K E T(不能两个同时指定) 。第三个参数 p r o t o c o l,除非你必须将其取消,否则就是准备依据它来创建套接字的那个 L A N A编号。第四个参数是空值,
因为你此刻正在指定自己的参数,而不是正在使用 W S A P R O TO C O L _ I N F O结构。第五个参数没有用。最后,把 d w F l a g s参数设为 W S A _ F L A G _ O V E R L A P P E D;根据所有 W S A S o c k e t调用,
指定 W S A _ F L A G _ O V E R L A P P E D。
第一种套接字创建法的不足之处是必须知道从哪一个有效 L A N A编号着手。不幸的是,
Wi n s o c k目前没有妙方把所有有效 L A N A编号列举出来。备用 Wi n s o c k可利用 W S A E n u m P r o t o c o l s
把所有传输协议列举出来。当然,也可利用 N C B E N U M命令调用 N e t b i o s,从而获得有效的
L A N A编号。第 5章对如何调用 W S A E n u m P r o t o c o l s进行了说明。下面的实例列举了所有的传输协议,搜查到一个 N e t B I O S传输,并针对各个协议分别建立了套接字。
116计计 第二部分 附 Winsock API 下载在上面的伪代码中,我们列举了可用的传输协议,并通过它们对属于 A F _ N E T B I O S地址家族的协议进行反复查找。接下来,我们要检查套接字类型,这里要查找的是 S O C K _ S E Q PA C K E T
类型的条目。如需要数据报,就检查 S O C K _ D G R A M。如果找到的套接字类型和条目匹配,我们就有一个可以使用的 N e t B I O S传输协议了。如果还需要一个 L A N A编号,就选用 W S A P R O TO C O L S _I N F O
结构中 i P r o t o c o l字段的绝对值。这个 L A N A的 i P r o t o c o l字段是 0 x 8 0 0 0 0 0 0 0,因为 0是 Wi n s o c k为特殊用途保留的。变量 j将包含一个值,表示有效传输协议有多少个。
6.5 AppleTalk
Wi n s o c k中,对 A p p l e Ta l k的支持已发布一段时间了,但鲜为人知。如果不与苹果公司的
M A C机通信,你可能不会选择 A p p l e Ta l k协议。从某种程度上来说,A p p l e Ta l k与 N e t B I O S类似,
因为两者都是针对每一个进程来进行名字注册的。也就是说,要使特定的名字广为人知,服务器必须对这个名字进行注册。客户机再用这个名字与服务器建立连接。究其本质,
A p p l e Ta l k名比 N e t B I O S名更为复杂。下一小节,我们将讨论如何为网络上使用 A p p l e Ta l k协议的计算机进行定址。
6.5.1 定址
A p p l e Ta l k名实际上是以三个独立的名字为基础的:名、类型和区。每个名字的长度可达
3 2个字符。这个名字标识机器上的进程及其关联套接字。类型是区的子群机制。传统意义上,
区是一个网络,它是由物理定位于同一个循环上、使用 A p p l e Ta l k协议的计算机构成的。微软的 A p p l e Ta l k实施方案允许 Wi n d o w s兼容机对自己定位的默认区进行指定。多个网络可通过桥接联在一起。这些易记的名字分别映射一个套接字编号、一个节点编号和一个网络编号。在特定的类型和区内,A p p l e Ta l k名必须是独一无二的。这项要求由“名字绑定协议” ( N B P)
来执行,该协议将一次查询在网上广播,以便知道这个名字是否已使用。与此同时,
A p p l e Ta l k利用“路由表维护协议” ( RT M P),动态地对链接在一起的各个 A p p l e Ta l k网络的路由进行查找。
下一个结构提供了从 Wi n s o c k为 A p p l e Ta l k主机定址的基础:
第 6章 计 地址家族和名字解析 计计 117下载注意,这个地址结构中只有字符或短整型数,没有友好名。 S O C K A D D R _ AT结构被投入
b i n d,c o n n e c t和 W S A c o n n e c t之类的 Wi n s o c k调用中,但如果要转换易于理解的名字,必须要求网络系统先对这个名字进行解析或注册。这是分别通过 g e t s o c k o p t或 s e t s o c k o p t调用来完成的。
6.5.2 AppleTalk名的注册对一个服务器而言,如果它打算注册特定名字,以便客户机可以很容易地与之建立连接,
就要利用 S O _ R E G I S T E R _ N A M E选项来调用 s e t s o c k o p t函数。牵涉到 A p l p l e Ta l k名的所有套接字选项,都要使用 W S H _ N B P _ N A M E结构,它的格式如下:
许多类型(比如说 W S H _ R E G I S T E R _ N A M E,W S H _ D E R E G I S T E R _ N A M E和
W S H _ R E M O V E _ N A M E)都是在这个 W S H _ N B P _ N A M E结构的基础上定义的。使用哪个类型要根据具体情况而定,看你是查找名字呢,还是注册名字或删除名字。
下面的代码实例解释了如何注册 A p p l e Ta l k名。
118计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 119下载大家首先注意到的是 M Y _ Z O N E,M Y _ T Y P E和 M Y _ O B J E C T这三个字串。记住,
A p p l e Ta l k名是三级式的。注意,区是一个星号,*” 。这是区字段中所用的特殊字符,用来指定计算机处在“当前”区。接下来,我们建立一个隶属于 A p p l e Ta l k协议 A D S P的 S O C K _ S T R E A M
类型的套接字。这个套接字建立之后,有一个利用一个地址结构进行的 b i n d调用,这个地址结构中有一个置零 s a t _ s o c k e t字段和唯一设置的协议家族字段。这是非常重要的,因为它为发出请求的用户应用在网络上建立了一个端点。注意,虽然调用 b i n d允许你在网络上执行简单操作,但它本身不允许你的应用接受客户机发出的接入连接请求。要接受客户机连接,必须在网络上注册你自己的名字,这是下一步的工作。
注册 A p p l e Ta l k名很简单。把 S O L _ A P P L E TA L K当作,l e v e l”参数,S O _ R E G I S T E R _ N A M E
当作 o p t n a m e参数投递出去,便可调用 s e t s o c k o p t。后两个参数是一个指针,它指向我们的
W S H _ R E G I S T E R _ N A M E结构及其长度。如果调用 s e t s o c k o p t成功,我们的服务器名便得以成功注册。如果调用失败,所请求的名字大概已为他人所用。返回的 Wi n s o c k 错误是
W S A E A D D R I N U S E( 1 0 0 4 8或 0 x 0 2 7 4 0 h) 。注意,对同时面向数据报和面向流的 A p p l e Ta l k协议来说,想接收数据的进程必须注册一个名字,以便客户机可向它发送数据报或与之建立连接。
6.5.3 AppleTalk名的解析同等的客户机这一端,应用通常通过友好名来得知服务器,而且必须把这个友好名解析成 Wi n s o c k调用所用的网络、节点和套接字编号。这是通过 SO_LOOKUP_ NAME选项调用
g e t s o c k o p t函数来完成的。执行 A p p l e Ta l k名的查找依赖于 W S A _ L O O K U P _ N A M E结构。这个结构及其相关结构的格式如下:
在利用 S O _ L O O K U P _ N A M E选项调用 g e t s o c k o p t时,我们把一个缓冲造型当作 W S H _
L O O K U P _ N A M E结构投递出去,并在第一个 L o o k u p Tu p l e成员内填写 W S H _ N B P _ N A M E。调用成功后,g e t s o c k o p t返回一个 W S H _ N B P _ T U P L E元素组成的数组,其中包含那个 A p p l e Ta l k
名的物理地址信息。程序清单 6 - 1中包含了 A t a l k n m,c文件,该文件对如何查找 A p p l e Ta l k名进行了解释。除此以外,程序清单 6 - 1还展示了如何列出所有的“已找到的” A p p l e Ta l k区以及如何找到用户的默认区。区信息可通过 g e t s o c k o p t选项 SO_LOOKUP _ZONES和 S O _ L O O K U P _
M Y Z O N E来获得。
程序清单 6-1 AppleTa l k名和区的查找
120计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 121下载
122计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 123下载
124计计 第二部分 附 Winsock API 下载在使用许多 A p p l e Ta l k套接字选项时 — 比如 S O _ L O O K U P _ M Y Z O N E,S O _ L O O K U P _
Z O N E S以及 S O _ L O O K U P _ N A M E— 需要为 g e t s o c k o p t调用提供更大的字符缓冲。如果调用要求你提供一个结构的选项,这个结构必须在所供字符缓冲之首。如果调用 g e t s o c k o p t成功,
这个函数就把返回的数据放在所供结构之后的字符缓冲中。我们来看看程序清单 6 - 1中的
S O _ L O O K U P _ N A M E这一部分。变量 c L o o k u p B u ff e r是一个用于 g e t s o c k o p t调用中的简单字符数组。首先,我们把它造型成 P W S H _ L O O K U P _ N A M E,并在里面填入想查找的名字信息。
然后,把这个缓冲投入 g e t s o c k o p t,再根据返回的结果,增加字符指针 p Tu p l e B u ff e r,这样,
令其指向 W S H _ L O O K U P _ N A M E结构之后的那个字符。接下来,再把这个字符指针造型成一个 PWSH_NBP_TUPLE WSH变 量,因 为 查 找 A p p l e Ta l k名 调 用 返 回 的 数 据 是 一 个
W S H _ N B P _ T U P L E结构组成的数组。一旦有了正确的起始位置和字元组类型,就可大功告成了。关于 A p p l e Ta l k地址家族特有的各种套接字选项的详细资料,请参考第 9章。
6.5.4 创建套接字
A p p l e Ta l k可用于 Winsock 1.1及稍后的版本,因此可任选套接字创建例程。再次提醒大家注意,指定基层 A p p l e Ta l k协议的方式有两种。其一,可为自己需要的协议提供 A t a l k w h,h中的相应定义。其二,利用 W S A E n u m P r o t o c o l s,然后投递 W S A P R O TO C O L _ I N F O结构,便可列举协议了。至于直接用 s o c k e t或 W S A S o c k e t创建套接字时各 A p p l e Ta l k协议所需的参数,均可参见表 6 - 1。
表 6-1 AppleTa l k协议和参数协 议 地址家族 套接字类型 协议类型
MSAFD AppleTa l k [ A D S P ] S O C K _ R D M AT P R O TO _ A D S P
MSAFD AppleTa l k S O C K _ S T R E A M AT P R O TO _ A D S P
[ A D S P ] [ P s e u d o - S t r e a m ] A F _ A P P L E TA L K
MSAFD AppleTa l k [ PA P ] S O C K _ R D M AT P R O TO _ PA P
MSAFD AppleTa l k [ RT M P ] S O C K _ D G R A M D D P P R O TO _ RT M P
MSAFD AppleTalk [ZIP] S O C K _ D G R A M D D P P R O TO _ Z I P
6.6 ATM
异步传输模式( AT M)协议是目前已有的最新协议之一,Windows 98和 Windows 2000平台上的 Winsock 2均支持它。 AT M通常用于 L A N和 WA N上的高速联网,也用于各种类型的通信,比如说要求高速通信的语音、视频和数据等。一般说来,AT M利用网络上的虚拟连接
( V C)来提供服务质量( Q O S)保证。正如大家即将看到的那样,Wi n s o c k能够通过 AT M地址家族来使用 AT M网络上的虚拟连接。 AT M网络(如图 6 - 1所示)一般由通过交换机(它们将
AT M网络桥接在一起)连接的端点(或计算机)构成。
针对 AT M协议编程时,需要明白这几点。首先,AT M是一个媒体类型,而不是一个真正的协议。也就是说,AT M类似于直接在以太网上写入以太帧。和以太网一样,AT M协议没有提供流控制。它是一个面向连接的协议,要么提供消息模式,要么提供流模式。这还意味着第 6章 计 地址家族和名字解析 计计 125下载如果数据不能快速发送出去,发送应用则可能溢出本地缓冲。同样地,接收应用必须频繁投递收到的数据:否则,接收缓冲填满之时,任何一个另外接入的数据都可能被丢弃。如果你的应用需要流控制,方法之一是在 AT M上使用 I P协议(它只是运行于 AT M网络上的 I P协议) 。
这样一来,应用便紧跟在上面描述的 I P地址家族之后。当然,AT M的确提供了比 I P好的一些好处,比如说“根式多播方案” (第 1 2章将对此进行说明);然而,要根据自己的应用需要来决定最适合你的那种协议。
图 6-1 ATM网络
6.6.1 定址一个 AT M网络有两个网络接口:用户网络接口( U N I)和网络节点接口( N N I) 。 U N I接口是在终端和 AT M交换机之间建立的,而 N N I接口则是在两个交换机之间建立的。各个接口都有自己相关的通信协议,具体说明如下:
■ U N I信号协议 允许终端在一个终端和一个 AT M交换机之间发送设置和控制信息,从而在 AT M网络上建立通信。注意,这个协议只限于一个终端和一个 AT M交换机之间的传输,不能直接通过交换机在 AT M网络上传输。
■ N N I信号协议 允许 AT M交换机在两个交换机之间交流路由选择和控制信息。
若想通过 Wi n s o c k设置 AT M连接,那么我们只讨论 U N I信号协议中的特定信息元素。目前,
Windows 2000和 Windows 98( S P 1)上的 Wi n s o c k可支持 U N I信号协议 3,1版本。
Wi n s o c k允许客户机/服务器通过设置“服务访问点” ( S A P)应用在 AT M网络上进行通信。这是利用 ATM UNI信号协议设置“服务访问点”之后形成的连接来完成的。 AT M是一个面向连接的协议,要求端点为进行通信,在 AT M网络上建立虚拟连接。对 AT M网络上通信用的套接字接口而言,S A P只是允许 Wi n s o c k应用通过 S O C K A D D R _ AT M地址结构对它进行注册和标识。 S A P一旦建立,Wi n s o c k就利用 U N I信号协议,向 AT M网络发出调用,通过这种方式,
便用这个 S A P在 AT M网络上的 Wi n s o c k 客户机和服务器之间建立一个虚拟连接。
S O C K A D D R _ AT M结构的格式如下:
ATM
转换 ATM
转换
ATM
转换
ATM
转换
ATM
终端
ATM
终端
s a t m _ f a m i l y应该一直为 A F _ AT M。 s a t m _ n u m b e r字段利用其中一个基本 AT M定址方案——
E,1 6 4和“网络服务访问点” ( N S A P),将事实上的 AT M地址表示成一个 AT M _ A D D R E S S结构。
N S A P也表示,N A S P式的 AT M终端系统地址” ( A E S A) 。 AT M _ A D D R E S S结构的格式如下:
A d d r e s s Ty p e字段定义特定的定址方案。如果是 E,1 6 4定址方案,这个字段就是 AT M _ E 1 6 4;
若是 N S A P式的定址方案,该字段就是 AT M _ N S A P。除此以外,在应用打算把套接字和一个
S A P绑定在一起时,还可将 A d d r e s s Ty p e字段设为表 6 - 2中定义的其他值。本章稍后将对此进行详细讨论。 N u m o f D i g i t s字段应该一直设为 AT M _ A D D R _ S I Z E。 A d d r字段表示事实上的 AT M
2 0字节的 E,1 6 4或 N A S P地址。
S O C K A D D R _ AT M结构的 s a t m _ b l l i和 s a t m _ b h l i这两个字段分别代表 AT M信号协议 中的
“宽带基层信息” ( B L L I)和“宽带高层信息” ( B L L I) 。一般说来,这些结构用于对 AT M连接上运行的协议堆栈进行标识。对几个 B L L I和 B H I L值已知组合的说明参见 ATM Form/ I E T F
(互联网工程任务组)文档(这些值的特定组合用于标识 AT M网络上的 L A N仿真,而另一种组合则用于标识 AT M网络上的原始 I P,如此等等) 。这些结构中的字段值都列在 ATM UNI 3.1标准一书中。 ATM Form/ I E T F文档都可在网上地址 h t t p,/ / w w w,i e t f,o rg找到。
表 6-2 AT M套接字地址类型
ATM_ADDRESS AddressTy p e设置 地 址 类 型
AT M _ E 1 6 4 E,1 6 4地址,与 S A P连接时使用
AT M _ N S A P N S A P式的 AT M终端系统地址( A E S A),与 S A P连接时使用
S A P _ F I E L D _ A N Y _ A E S A _ S E L N S A P式的 AT M终端系统地址,带有通配的八个选择符。
在绑定套接字和 S A P时使用
S A P _ F I E L D _ A N Y _ A E S A _ R E S T N S A P式的终端系统地址,不包括通配的八个选择符,
但其他的所有八个字符都有。在绑定套接字和 S A P时使用
B H L I和 B L L I数据结构的格式如下:
126计计 第二部分 附 Winsock API 下载关于这些字段的定义和用法,不在本书讨论之列。如果一个应用只想在 AT M网络上建立
Wi n s o c k通信,就应该把 B H L I和 B L L I结构中的下列字段设为 S A P _ F I E L D _ A B S E N T值:
■ AT M _ B L L I— 第二层协议。
■ AT M _ B L L I— 第三层协议。
■ AT M _ B H L I— 高层信息类型( H i g h L a y e r I n f o Ty p e) 。
在上述字段被设为这个值时,不再使用这两个结构中的其他字段。下面的伪代码演示了一个应用如何用 S O C K A D D R _ AT M结构为 N S A P地址设置 S A P:
AT M地址一般表示成一个十六进制的 A S C I I 字符串,由 4 0个字符组成,与组成
AT M _ A D D R E S S结构 N S A P式或 E,1 6 4地址的 2 0个字节相对应。比如,AT M _ N S A P式的地址可能像这样:
把这个字串转换成一个 2 0字节的地址相当麻烦。然而,Wi n s o c k提供了一个与协议无关的
A P I函数,W S A S t r i n g To A d d r e s s,利用它,便可把一个 4 0个字符的 AT M十六进制 A S C I I字串转换成一个 AT M _ A D D R E S S结构。我们将在本章最后着重讲一讲这个 A P I函数。把一个十六进制 A S C I I字串转换成十六进制(二进制)格式的另一种方法是利用程序清单 6 - 2中定义的 A t o H
函数。该函数不属于 Wi n s o c k。但是,和前一个函数比较起来,它更容易开发,大家可在第 7
章中的实例中看到它。
程序清单 6-2 用于转换 AT M十六进制字串的函数第 6章 计 地址家族和名字解析 计计 127下载
6.6.2 创建套接字
AT M中,应用只能建立面向连接的套接字,因为 AT M只允许通过虚拟连接进行的通信。
因此,数据的传输的形式是字节流或采用面向消息的形式。要利用 AT M协议打开一个套接字,
先通过地址家族 A F _ AT M和套接字类型 S O C K _ R AW调用 s o c k e t函数或 W S A S o c k e t函数,然后再把协议字段设为 AT M P R O TO _ A A L 5即可。比如:
默认状态下,打开套接字(比如上面这个例子)建立一个面向流的 AT M套接字。 Wi n d o w s
还有一个富有特色的 AT M提供者,可执行面向消息的数据传输。使用这个面向消息的提供者要求用户为 W S A S函数显式指定原始 AT M协议提供者,这是利用 W S A P R O TO C O L _ I N F O结构完成的(关于这一结构,我们曾在第 5章详细讲过) 。这一点是必须的,因为 s o c k e t和 W S A S o c k e t
这两个调用中的三个元素(地址家族、套接字类型和协议)均和 Wi n s o c k中可以使用的每一个
128计计 第二部分 附 Winsock API 下载
AT M协议提供者相符。默认状态下,Wi n s o c k会返回与这三个属性相符的协议条目,并把这个协议条目标注成默认设置(在面向流的提供者情形下如此) 。下面的伪代码将演示如何获得
AT M面向消息协议提供者以及如何建立一个套接字:
6.6.3 把套接字和 SAP绑定在一起事实上,AT M地址是相当复杂的,因为它们由 2 0个字节组成,其中包含许多信息元素。
除了最后一个字节外,这些元素的所有其他字节,Wi n s o c k程序员均不用下功夫去记。 N S A P
式地址和 E,1 6 4地址中的最后一个字节均代表一个特定的选择符值,该值唯一允许应用定义和指定端点上特定的 S A P。正如我们前面指出的那样,Wi n s o c k利用 S A P建立 AT M网络上的通信。
Wi n s o c k应用打算在 AT M网络上进行通信时,服务器应用必须在一个端点上注册一个 S A P,
并等待客户机应用根据已注册的 S A P接入。对客户机应用来说,这只包括通过 AT M _ E 1 6 4或
AT M _ N S A P地址类型设置 S O C K A D D R _ AT M结构和提供与服务器 S A P关联在一起的那个 AT M
地址。要建立一个用于监听连接的套接字,应用必须先为指定的 A F _ AT M地址家族建立一个套接字。这个套接字一旦建立,应用就必须像表 6 - 2中定义的那样,利用 S A P _ F I E L D _ A N Y _
A E S A _ S E L,S A P _ F I E L D _ A N Y _ A E S A _ R E S T,AT M _ E 1 6 4或 AT M _ N S A P地址类型来定义
S O C K A D D R _ AT M结构。对 AT M套接字而言,应用一旦调用 Wi n s o c k的 bind API函数(我们将在第 7章对该函数进行讲述),就会建立一个 S A P,这些地址类型对 Wi n s o c k在端点上建立 S A P
的方式进行了定义。
S A P _ F I E L D _ A N Y _ A E S A _ S E L地址类型要求 Wi n s o c k建立一个能对任何一种 AT M Wi n s o c k
连接进行监听的 S A P,这就是通常所说的通配 AT M地址和选择符。这意味着监听连接的这个端点只能绑定一个套接字 — 另一个套接字打算与这个地址类型绑定在一起,就会失败,并出现这样的 Wi n s o c k错误 W S A E A D D R I N U S E。然而,你也可以将另一个套接字和指定选择符上的端点显式绑定在一起。而显式和端点上的指定选择符绑定在一起的 S A P,则可用地址类型 S A P _ F I E L D _ A N Y _ A E S A _ R E S T来建立。这就是人们常说的只有 AT M地址,而没有选择符的“通配” 。对端点上的一个指定选择符而言,一次只能绑定一个套接字,否则 b i n d调用就会失败,并返回错误 W S A E A D D R I N U S E。在使用 S A P _ F E I L D _ A N Y _ A E S A _ S E L类型时,应该在 AT M _ A D D R E S S结构中指定一个均由零组成的 AT M地址。如果使用的是 S A P _ F I E L D _
A N Y _ A E S A _ R E S T,就应该把这个 AT M地址的前 1 9个字节指定为 0,最后一个字节应该是准第 6章 计 地址家族和名字解析 计计 129下载备使用的选择符的编号。
和显式选择符( S A P _ F I E L D _ A N Y _ A E S A _ R E S T)绑定在一起的套接字优先于和通配选择符( S A P _ F I E L D _ A N Y _ A E S A _ S E L)绑定在一起的套接字。连接时,系统会优先采用和显式选择符( S A P _ F I E L D _ A N Y _ A E S A _ R E S T)或显式接口( AT M _ N S A P和 AT M _ E 1 6 4)绑定在一起的套接字(也就是说,如果一个连接接入套接字显式监听的指定端点和选择符,这个套接字就会获得连接) 。只有在无显式绑定套接字可用的情况下,才会用通配选择符套接字来获得连接。第 7章将进一步说明如何设置一个套接字,使其监听 S A P上的连接。
最后,可通过一个名为 A t m a d m,e x e实用程序获得所有的 AT M地址和端点上虚拟连接信息。
在开发 AT M应用程序和需要了解端点上哪些接口可用时,这个实例程序相当有用。下面表 6 - 3
中列出的命令行选项都可用。
表 6-3 命令行选项参数 说 明
- c 列出所有的连接(指的是虚伪连接,V C) 。列出远程地址和本地接口
- a 列出所有已注册的地址(比如说所有的本地 AT M接口及其地址)
- s 打印特性(当前调用次数,收到或发出的传信和 I L M I包数,等等)
6.6.4 名字解析目前,尚且没有命名提供者可用于 Wi n s o c k下的 AT M协议。因此,不幸的便是要求应用对这个长达 2 0个字节的 AT M地址进行指定,以便建立 AT M网络上的套接字通信。第 1 0章将讨论
Windows 2000域名空间(一般用于对带有友好服务名的 AT M地址进行注册) 。
6.7 Winsock 2支持的其他函数
Winsock 2提供了两个有用的支持函数,它们是 W S A A d d r e s s To S t r i n g和 W S A S t r i n g To A d d r e s s。
这两个函数提供了一个与协议无关的转换方法,可以把 S O C K A D D R结构转换成一个格式化的字符串,反之亦然。由于这两个函数都是与协议无关的,所以它们要求传输协议能支持字串转换。目前,它们只能用于 A F _ I N E T和 A F _ AT M这两个地址家族。 W S A A d d r e s s To S t r i n g函数的定义如下:
l p s a A d d r e s s参数代表特定协议(其中包括即将转换成字串的那个地址)的 S O C K A D D R结构。
这个 S O C K A D D R结构的长度则由 d w A d d r e s s L e n g t h参数指定。不同的协议,其长度也不相同。
l p P r o t o c o l I n f o参数是可选的,表示协议提供者。协议提供者可通过 WSAEnumProtocols API函数获得,参见第 5章。如果指定了 N U L L,对这个函数的调用就会采用第一个协议(它支持
l p s a A d d r e s s中指定的协议家族)的提供者。 l p s z A d d r e s s S t r i n g参数是一个缓冲,它收到的是易于理解的地址字串。 l p d w A d d r e s s S t r i n g L e n g t h参数代表 l p s z A d d r e s s S t r i n g的长度。根据结果,它返
130计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 131下载回实际复制到 l p s z A d d r e s s S t r i n g中的字串长度。如果提供的缓冲不够大,这个函数调用就会失败,
并出现错误 W S A E FA U LT,而 l p d w A d d r e s s S t r i n g L e n g t h参数也会根据所需要的字节长度而更新。
相反地,W S A S t r i n g ToAddress API函数采用易于理解的地址串,并将它转换成一个
S O C K A D D R结构。 W S A S t r i n g To A d d r e s s的定义如下:
A d d r e s s S t r i n g参数是一个易于理解的地址串。表 6 - 4对该字串的格式进行了说明。
表 6-4 地址串的格式地址家族 字串格式
I P X X X,X X X,X X X,X X X,Y— X代表 I P地址串中的一组八字符,Y则表示端口号
AT M N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N— 4 0个 N
表示一个以十六进制表示的、由 2 0个字节组成的 AT M地址
A d d r e s s f a m i l y参数代表 A d d r e s s S t r i n g参数的地址家族类型。 l p P r o t o c o l I n f o参数是可选的,
代表一个协议提供者。如果把这个参数设为 N U L L,Wi n s o c k就会在第一个可用的协议提供者中进行搜索,查找 A d d r e s s f a m i l y参数所指定地址家族类型。如果想选定某个特定的协议提供者,WSAEnumProtocol API函数就可为你提供一个列表,已安装在系统中、可用的协议提供者都列在上面。 A d d r e s s缓冲参数选择的是收到信息的、地址串中的 S O C K A D D R结构。
l p A d d r e s s L e n g t h参数代表所生成的 S O C K A D D R结构的长度。
6.8 小结这一章论述了 Wi n s o c k支持的协议地址家族,说明了各个家族特有的定址属性。针对每个地址家族,我们还讨论了如何创建套接字和如何设置套接字地址结构,以便开始通过协议进行通信。下一章,我们将描述适用于 Wi n s o c k的基本通信技术,并把它们应用到本章讨论的所有地址家族上。
Wi n s o c k支持的协议以及各协议如何把一个指定家族的地址解析成网络上一台具体的机器。
Winsock 2引入了几个新的、与协议无关的函数,它们可和任何一个地址家族一起使用;但是大多数情况下,各协议家族都有自己的地址解析机制,要么通过一个函数,要么作为一个投给 g e t s o c k o p t的选项。本章只讲解各协议组成地址结构时所需的一些基本知识。第 1 0章讨论注册和名字解析函数,这些函数对特定协议家族服务进行声明(这和简单的名字解析稍有不同) 。
关于直接名字解析、服务声明与解析之间的差别,可参见第 1 0章。
对已讲过的地址家族来说,我们将进一步探讨如何为网络上的一台机器定址。然后,再针对各个家族建立套接字。除此以外,还要讨论协议独有的名字解析选项。
6.1 IP
网际协议( Internet Protocol,IP)是一种用于互联网的网络协议,已经广为人知。它可广泛用于大多数计算机操作系统上,也可用于大多数局域网 L A N(比如办公室小型网络)和广域网 WA N(比如说互联网) 。从它的设计看来,I P是一个无连接的协议,不能保证数据投递万无一失。两个比它高级的协议( T C P和 U D P)用于依赖 I P协议的数据通信。
6.1.1 TCP
面向连接的通信是通过“传输控制协议” ( Transmission Control Protocol,TCP)来完成的。
T C P提供两台计算机之间的可靠无错的数据传输。应用程序利用 T C P进行通信时,源和目标之间会建立一个虚拟连接。这个连接一旦建立,两台计算机之间就可以把数据当作一个双向字节流进行交换。
6.1.2 UDP
无连接通信是通过“用户数据报协议” ( User Datagram Protocol,UDP)来完成的。 U D P
不保障可靠数据的传输,但能够向若干个目标发送数据,接收发自若干个源的数据。简单地说,如果一个客户机向服务器发送数据,这一数据会立即发出,不管服务器是否已准备接收数据。如果服务器收到了客户机的数据,它不会确认收到与否。数据传输方法采用的是数据报。
T C P和 U D P两者都利用 I P来进行数据传输,一般称为 T C P / I P和 U D P / I P。 Wi n s o c k通过
A F _ I N E T地址家族为 I P通信定址,这个地址家族的定义在 Winsock 1.h和 Winsock 2.h中。
6.1.3 定址
I P中,计算机都分配有一个 I P地址,用一个 3 2位数来表示,正式的称呼是,I P v 4地址” 。
客户机需要通过 T C P或 U D P和服务器通信时,必须指定服务器的 I P地址和服务端口号。另外,
第 6章 计 地址家族和名字解析 计计 103下载服务器打算监听接入客户机请求时,也必须指定一个 I P地址和一个端口号。 Wi n s o c k中,应用通过 S O C K A D D R _ I N结构来指定 I P地址和服务端口信息,该结构的格式如下:
s i n _ f a m i l y字段必须设为 A F _ I N E T,以告知 Wi n s o c k我们此时正在使用 I P地址家族。
IP协议第 6版
I P协议第 6版对原来的 I P协议规格进行了改进,将 I P地址扩展到 1 6个字节。随着 I P v 4
的退场,不久的将来,I P v 6的地位显得越来越重要。许多 Wi n s o c k头文件中都包含针对
I P v 6结构的条件定义;但是当前的 Wi n 3 2平台均没有提供 I P v 6网络堆栈(包括 Wi n d o w s
2 0 0 0在内) 。,微软研究部”已开发出一个试验性的 I P v 6堆栈,可从 h t t p,/ / r e s e a r c h,
m i c r o s o f t,c o m / m s t r i p v 6 /下载;然而,该堆栈未获支持,而且我们不打算深入第 6版协议中专有的特性。
准备使用哪个 T C P或 U D P通信端口来标识服务器服务这一问题,则由 s i n _ p o r t字段定义。
在选择端口时,应用必须特别小心,因为有些可用端口号是为“已知的” (即固定的)服务保留的(比如说文件传输协议和超文本传输协议,即 F T P和 H T T P) 。,已知的协议”,即固定协议,采用的端口由“互联网编号分配认证( I A N A),控制和分配,RFC 1700中说明编号。从本质上说,端口号分为下面这三类:,已知”端口、已注册端口、动态和(或)私用端口。
■ 0 ~ 1 0 2 3由 I A N A控制,是为固定服务保留的。
■ 1 0 2 4 ~ 4 9 1 5 1是 I A N A列出来的、已注册的端口,供普通用户的普通用户进程或程序使用。
■ 4 9 1 5 2 ~ 6 5 5 3 5是动态和(或)私用端口。
普通用户应用应该选择 1 0 2 4 ~ 4 9 1 5 1之间的已注册端口,从而避免端口号已被另一个应用或系统服务所用。此外,4 9 1 5 2 ~ 6 5 5 3 5之间的端口可自由使用,因为 I A N A这些端口上没有注册服务。在使用 bind API函数时,如果一个应用和主机上的另一个应用采用的端口号绑定在一起,系统就会返回 Wi n s o c k错误 W S A E A D D R I N U S E。第 7章将深入阐述 Wi n s o c k绑定进程。
S O C K A D D R _ I N结构的 s i n _ a d d r字段用于把一个 I P地址保存为一个 4字节的数,它是无符号长整数类型。根据这个字段的不同用法,还可表示一个本地或远程 I P地址。 I P地址一般是用“互联网标准点分表示法” (像 a,b,c,d一样)指定的,每个字母代表一个字节数,从左到右分配一个 4字节的无符号长整数。最后一个字段 sin_ zero,只充当填充项的职责,以使
S O C K A D D R _ I N结构和 S O C K A D D R结构的长度一样。
一个有用的、名为 i n e t _ a d d r的支持函数,可把一个点式 I P地址转换成一个 3 2位的无符号长整数。它的定义如下:
unsigned long inet_addr(
const char FAR *cp
);
c p字段是一个空中止字符串,它认可点式表示法的 I P地址。注意,这个函数把 I P地址当作一个按网络字节顺序排列的 3 2位无符号长整数返回(网络字节顺序在下面的“字节排序”小节中简要说明) 。
1,特殊地址对于特定情况下的套接字行为,有两个特殊 I P地址可对它们产生影响。特殊地址
I N A D D R _ A N Y允许服务器应用监听主机计算机上面每个网络接口上的客户机活动。一般情况下,在该地址绑定套接字和本地接口时,网络应用才利用这个地址来监听连接。如果你有一个多址系统,这个地址就允许一个独立应用接受发自多个接口的回应。
特殊地址 I N A D D R _ B R O A D C A S T用于在一个 I P网络中发送广播 U D P数据报。要使用这个特殊地址,需要应用设置套接字选项 S O _ B R O A D C A S T。第 9章将对该选项进行详细论述。
2,字节排序针对“大头” ( b i g - e n d i a n)和“小头” ( l i t t l e - e n d i a n)形式的编号,不同的计算机处理器的表示方法有所不同,这由各自的设计决定。比如,Intel 86处理器上,用“小头”形式来表示多字节编号:字节的排序是从最无意义的字节到最有意义的字节。在计算机中把 I P地址和端口号指定成多字节数时,这个数就按“主机字节” ( h o s t - b y t e)顺序来表示。但是,如果在网络上指定 I P地址和端口号,“互联网联网标准”指定多字节值必须用“大头”形式来表示
(从最有意义的字节到最无意义的字节),一般称之为“网络字节” ( n e t w o r k - b y t e)顺序。
有一系列的函数可用于多字节数的转换,把它们从主机字节顺序转换成网络字节顺序,
反之亦然。下面四个 A P I函数便将一个数从主机字节顺序转换成网络字节顺序:
h t o n l和 W S A H t o n l的 h o s t l o n g参数是按主机字节顺序的一个 4字节数。 h t o n l函数返回的数顺序是网络字节顺序,而 W S A H t o n l函数通过 l p n e t l o n g参数返回的数顺序是网络字节顺序。
h t o n s和 W S A H t o n s的 h o s t s h o r t参数是按主机字节顺序的一个 2字节数。 h t o n s函数把这个数当作按网络字节顺序的一个 2字节值返回,而 W S A H t o n s函数通过 l p n e t s h o r t参数把这个数返回。
下面这四个是前面四个函数的反向函数:它们把网络字节顺序转换成主机字节顺序:
104计计 第二部分 附 Winsock API 下载现在,我们打算演示一下如何利用上面描述的 i n e t _ a d d r 和 h t o n s 函数来创建
S O C K A D D R _ I N结构。
6.1.4 创建套接字创建一个 I P套接字的好处是便于应用能够通过 T C P,U D P和 I P协议进行通信。如要用 T C P
协议打开一个 I P套接字,需调用带有地址家族 A F _ I N E T和套接字类型 S O C K _ S T R E A M的
s o c k e t函数或 W S A S o c k e t函数,并把协议字段设成 0,方式如下:
要利用 U D P协议打开 I P套接字,只须指定套接字类型,用这个指定的套接字类型代替
s o c k e t函数中的 S O C K _ S T R E A M和上面的 W S A S o c k e t调用。还可以打开一个套接字通过 I P直接通信。这是把套接字类型设成 S O C K _ R AW来完成的。第 1 3章将对 S O C K _ R AW选项进行深入探讨。
6.1.5 名字解析
Wi n s o c k应用打算通过 I P和主机通信时,必须知道这个主机的 I P地址。依用户看来,I P地址是不容易记的。在指定机器时,许多人更愿意利用一个易记的、友好的主机名而不是 I P地址。 Wi n s o c k提供了两个支持函数,它们有助于用户把一个主机名解析成 I P地址。
Wi n d o w s套接字 g e t h o s t b y n a m e和 WSAAsynGetHostByName API函数从主机数据库中取回与指定的主机名对应的主机信息。两个函数均返回一个 H O S T E N T结构,该结构的格式如下:
第 6章 计 地址家族和名字解析 计计 105下载
h _ n a m e字段是正式的主机名。如果网络采用了“域内命名系统” ( D N S),它就是导致命名服务器返回响应的“全限定域名” ( F Q D N) 。如果网络使用一个本地“多主机”文件,主机名就是 I P地址之后的第一个条目。 h _ a l i a s e s字段是一个由主机备用名组成的空中止数组。
h _ a d d r t y p e表示即将返回的地址家族。 h _ l e n g t h字段则对 h _ a d d r _ l i s t字段中的每一个地址定义字节长度进行定义。 h _ a d d r _ l i s t字段是一个由主机 I P地址组成的空中止数组(可以为一个主机分配若干个 I P地址) 。这个数组中的每个地址都是按网络字节顺序返回的。一般情况下,应用程序都采用该数组中的第一个地址。但是,如果返回的地址不止一个,应用程序就会相应地选择一个最恰当的,而不是一直都用第一个地址。
gethostbyname API函数的定义如下:
n a m e参数表示准备查找的那个主机的友好名。如果这个函数调用成功,系统就会返回一个指向 H O S T E N T结构的指针。注意,保存 H O S T E N T结构的是系统内存。应用程序不应该依靠它来维护状态。由于该内存由系统维护,因此,你的应用程序不必释放这个已返回的结构。
WSAAsyncGetHostByName API函数是 g e t h o s t b y n a m e函数的异步版,后一个函数在结束时,利用 Wi n d o w s消息向应用程序发出通知。 W S A A s y n G e t H o s t B y N a m e的定义如下:
b W n d参数是窗口句柄,异步请求结束时,这个句柄将收到一条消息。 w M s g参数是异步请求结束时收到的窗口消息。 n a m e参数代表我们正在查找的主机之用户友好名。 b u f参数是一个指针,它指向接收 H O S T E N T数据的那个数据域。这个缓冲区必须大于 H O S T E N T结构,应该设为 M A X G E T H O S T S T R U C T中定义的最大长度。
另外两个用于获得主机信息的函数是,g e t h o s t b y a d d r和 WSAAsynGetHostByName API函数,它们是为获得与 I P网络地址相应的主机信息而设计的。在有了主机 I P地址,并打算查找其用户友好名时,这两个函数非常有用。 g e t h o s t b y a d d r函数的定义如下:
a d d r参数是指向一个 I P地址的指针,这个地址按网络字节顺序排列。 l e n参数用于指定 a d d r
参数的字节长度。 t y p e 参数将指定 A F _ I N E T 值,这个值表明指定类型是 I P地址。
WSAAsyncGetHostByAddr API函数是 g e t h o s t b y a d d r函数的异步版。
端口号
106计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 107下载应用打算与运行于本地或远程计算机上的服务进行通信时,除了要知道远程计算机的 I P
地址外,还必须知道服务的端口号。在使用 T C P和 U D P时,应用必须决定计划通过哪些端口进行通信。有几个“已知的端口号”是服务器服务保留的,这些服务支持比 T C P高级的协议
(比如 T C P和 S P X) 。举个例子来说,端口 2 1是为 F T P预留的,端口 8 0是为 F T T P预留的。正如前面提到的那样,已知的服务一般都采用 1 ~ 1 0 2 3之间的端口号来设置协议。如果你正在开发一个不使用任何一种已知服务的 T C P应用,就要考虑采用 1 0 2 3以上的端口,以免重复。通过调用 g e t s e r v b y n a m e和 W S A A s y n c G e t S e r v B y N a m e函数,便可获得已知服务的端口号。这两个函数只从名为 s e r v i c e s的文件中获得静态信息。 Windows 95和 Windows 98中,服务文件位于
% W I N D O W S%下面;在 Windows NT 和 Windows 2000中,则位于% W I N D O W S%
\ S y s t e m 3 2 \ D r i v e r s \ E t c下面。 g e t s e r v b y n a m e函数的定义如下:
n a m e参数代表准备查找的服务名。举个例子来说,如果你正在定位 F T P端口,就应该把
n a m e参数设成指向字串,f t p” 。 p r o t o参数随便指向一个字串,这个字串表明 n a m e中的服务是在这个参数中的协议下面注册的。 W S A A s y n c G e t S e r v B y N a m e函数是 g e t s e r v b y n a m e函数的异步版。
Windows 2000中有一个新的注册和请求 T C P及 U D P服务信息的动态方法。服务器应用可利用 W S A S e t S e r v i c e函数来注册服务名,I P地址和服务的端口号。客户机应用可利用这三个 A P I
函数的组合请求这条服务信息,这三个函数是 W S A L o o k u p S e r v i c e B e g i n,W S A L o o k u p S e r v i c e N e x t
和 W S A L o o k u p S e r v i c e E n d。第 1 0章将对此进行讨论。
6.2 红外线套接字红外线套接字称为 I r S o c k,它是一个令人兴奋不已的新技术,首先在 Wi n d o w s平台上亮相。
红外线套接字允许两台计算机通过红外线串行端口进行通信。目前,红外线套接字可在
Windows 98和 Windows 2000上使用。红外线套接字不同于传统意义上针对便携机的短暂性而设计的套接字。它们展示了一种新的名字解析模型,下一小节中将对此进行讨论。
6.2.1 定址由于带有“红外线数据联盟” ( Infrared Data Association,IrDA)设备的大多数计算机可能经常性地拆卸,传统的名字解析方案不能满足人们的需求。传统解析方法充当命名服务器之类的静态资源 — 人们在移动正在运行网络客户任务的手提式电脑或膝上型计算机时,是不能使用这些资源的。为解决这一问题,I r D A就设计成了这样:无须在整个大型网络上,只须用一种特定的方式浏览范围内的资源,因此,I r D A没有使用标准的 Wi n s o c k命名服务函数和
I P定址。相反,命名服务已并入通信流,另外还引入了一个新的地址家族,以支持与红外线串行端口绑定在一起的服务。 I r S o c k地址结构中包含一个服务名(它对绑定和连接调用中所使用的应用进行描述)和一个设备标识符(描述运行服务的设备) 。这里的服务名和设备标识符类似于传统 T C P / I P套接字所用的 I P地址和端口号字元组。 I r S o c k地址结构的定义如下:
i r d a A d d r e s s F a m i l y字段一直都是 A F _ I R D A。 i r d a D e v i c e I D是一个 4字符的字串,用于唯一性地标识特定服务所运行的设备。在建立 I r S o c k服务器时,这个字段是忽略不计的。但是对客户机而言,却非常重要,因为它指定的是准备连接的那个 I r D A设备(也可能有若干个) 。最后,
i r d a S e r v i c e N a m e字段是服务名,应用要么利用这项服务对其本身进行注册,要么试着与这项服务建立连接。
6.2.2 名字解析定址可以利用,I r D A逻辑服务访问点选择符( L S A P - S E L),或“信息访问服务” ( I A S)
注册的服务为基础。 I A S从一个 L S A P - S E L中摘出一项服务,并把它置入用户友好的文本服务名中,方式和互联网域名服务器把名字映射到数字化 I P地址差不多。要成功建立一个连接,
既可以用 L S A P - S E L,又可以用用户友好名。不过,用户友好名需要名字解析。大多数时候,
都不要使用直接的 L S A P - S E L“地址”,因为 I r D A服务的地址空间是限制了的。 Wi n 3 2实施方案允许 L S A P - S E L整数标识符,标识符的范围是 1到 1 2 7。从本质上说,我们可把 I A S服务器当作一个 W I N S服务器,因为它把 L S A P - S E L和一个文字化的服务名关联在一起。
事实上的 I A S条目有三个重要字段:类名、属性和属性值。举个例子来说,一个服务器希望在服务名 M y S e r v e r下对其本身进行注册。这是服务器通过相应的 S O C K A D D R _ I R D A结构执行绑定调用时完成的。这种情况一旦发生,就会增加一个 I A S条目,该条目中包括类名
M y S e r v e r、属性 I r D A,Ti n y T P,L s a p - S E L和属性值 3。属性值就是下一个未用过的 L S A P - S E L,
这个 L S A P - S E L 是系统根据注册来分配的。另一方面,客户机向连接调用投递一个
S O C K A D D R _ I R D A 结构。随后便开始 I A S 查找,查找带有类名 M y S e r v e r 和属性
I r D A,Ti n y T P,L s a p - S E L的那项服务。 I A S查询会返回 3这个值。用户可利用 g e t s o c k e t o p t调用中的套接字选项 I R L M P _ I A S _ Q U E RY来定制自己的 I A S查询。
如果打算完全忽略 I A S(一般不建议使用),则可为客户机准备连接的服务名或终端直接指定一个 L A S P - S E L地址。忽略 I A S后,就只能和不提供任何 I A S注册的老 I r D A设备(比如红外线打印机)进行通信。把 S O C K A D D R _ I R D A结构中的服务名指定为 L S A P - S E L - x x x,就可忽略 I A S注册和查找。其中,x x x处是属性值,其范围在 1到 1 2 7之间。对服务器而言,这样会直接为该服务器分配特定的 L S A P - S E L地址(假定这个 L S A P - S E L地址尚未使用) 。对客户机而言,这样会忽略 I A S查找,并试图马上与运行于指定的 L S A P - S E L上的任何一项服务建立连接。
6.2.3 红外线设备列举由于红外线设备的使用地点不固定,因此,必须有一种方法,可以动态地把特定范围内的所有可用红外线设备列举出来。我们先从 Windows CE实施方案和 Windows 98及 Wi n d o w s
2 0 0 0实施方案之间的几点差别谈起。 Windows CE先于其他平台支持 I r S o c k,并提供少量与红外线设备有关的信息。后来,Windows 98和 Windows 2000也开始支持 I r S o c k,但它们新增了另外的“提示”信息,该信息是由列举请求返回的(关于提示信息,我们稍后将简要论述) 。
108计计 第二部分 附 Winsock API 下载这样一来,Windows CE的 A F _ i r d a,h头文件中包含的是原始的、少量的结构定义;但是,其他平台提供的新的头文件中包含的则是目前支持 I r S o c k的各个平台的条件结构定义。为了保持一致,我们建议大家采用较新的 A f _ i r d a,h头文件。
列举临近红外线设备的方法是采用 g e t s o c k o p t的 I R L M P _ E N U M _ D E V I C E命令。
D E V I C E L I S T结构被当作 o p t v a l参数投递。这里有两个结构,一个针对 Windows 98和 Wi n d o w s
2 0 0 0,另一个针对 Windows CE。这两个结构的格式如下:
Windows 98和 Windows 2000结构与 Windows CE结构之间的唯一区别是 Windows 98和
Windows 2000结构中包含一个 W I N D O W S _ I R D A _ D E V I C E _ I N F O数组,该数组与 W C E _
I R D A _ D E V I C E _ I N F O结构的数组相对应。条件性的 # d e f i n e指令根据目标平台,声明
D E V I C E L I S T结构是正确的。同样,也有对 I R D A _ D E V I C E _ I N F O结构的两个声明:
# d e f i n e指令根据目标平台,向正确的结构定义声明 I R D A _ D E V I C E _ I N F O。
正如前面提到的那样,真正用于列举红外线设备的函数是带有 I R L M P _ E N U M _ D E V I C E S
选项的 g e t s o c k o p t函数。下面这一段代码,可把邻近的所有红外线设备 I D列举出来:
第 6章 计 地址家族和名字解析 计计 109下载在向 g e t s o c k o p t调用投递一个 D E V I C E L I S T结构之前,别忘了把 n u m D e v i c e字段设成 0。一次成功列举会把 n u m D e v i c e字段设成一个大于 0的值,并把 D e v i c e字段中 I R D A _ D E V I C E _ I N F O
结构数量设为前一个值。同时,在实际应用中,为检查新使用的设备,可能会多次执行
g e t s o c k o p t。举个例子来说,一个很好的例子就是试着进行五次或少于五次的红外线设备查找。
方法很简单:在未成功列举之后,利用短期调用 S l e e p,把该调用置入循环即可。
现在,大家已知道如何列举红外线设备,创建一个客户机或服务器就更简单了。同级的服务器端更为简单,因为它像一个“普通”服务器。也就是说,不需要额外的步骤。创建
I r S o c k服务器的常见步骤如下;
1) 建立一个地址家族 A F _ I R D A套接字和套接字类型 S O C K _ S T R E A M。
2) 用服务器的服务名填写一个 S O C K A D D R _ I R D A结构。
3) 利用套接字句柄和 S O C K A D D R _ I R D A结构调用 b i n d。
4) 利用套接字句柄和 b a c k l o g边限调用 l i s t e n。
5) 为接入客户机锁定一个 a c c e p t调用。
建立客户机的步骤稍微有些复杂,因为必须先把红外线设备列举出来。建立 I r S o c k客户机所需步骤如下:
1) 建立地址家族 A F _ I R D A套接字和套接字类型 S O C K - S T R E A M。
2) 调用有 I R L M P _ E N U M _ D E V I C E S选项的 g e t s o c k o p t函数,列举所有可用的红外线设备。
3) 针对返回的每个设备,利用设备 I D和准备连接的服务名填写一个 SOCKADDR_ IRDA
结构。
4) 利用套接字句柄和 S O C K A D D R _ I R D A结构,调用 c o n n e c t函数。针对步骤 3)中所填的结构,重复步骤 4),直到连接成功。
6.2.4 查询 IAS
要知道特定服务是否在特定的设备上运行,有两种方法。第一种是真正与特定服务连接;另一种是向 I A S查询特定的服务名。两种方法都要求列举红外线设备,然后对每一个设备进行查询直到达到目的或所有的设备都查完。执行查找是调用带有 I R L M P _ I A S _ Q U E RY选项的 g e t s o c k o p t函数来完成的。再次提醒大家注意,I A S _ Q U E RY结构有两个,一个针对
Windows 98和 Windows 2000,另一个针对 Windows CE。各结构的格式如下:
110计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 111下载大家可看到,除了特定字符数组的长度不同之外,这两个结构的格式是差不多的。
要对特定服务的 L S A P - S E L数有多少进行查询,很简单:把 i r d a C l a s s N a m e字段设为 L S A P -
S E L的属性字串,即 I r D A,I r L M P,L s a p S e l,然后,把 i r d a A t t r i b u t e N a m e字段设成准备查询的那个服务名。除此以外,还必须用范围内的有效设备来设置 i r d a D e v i c e I D字段。
6.2.5 创建套接字红外线套接字的创建很简单。几乎不需要任何选项,这是因为 I r S o c k只支持面向连接的数据流。下面的代码说明了如何利用 s o c k e t或 W S A S o c k e t调用来建立红外线套接字。由于
Winsock 1.1的限制,必须采用 Windows CE的 s o c k e t。
如果不想因循守旧,可把 I R D A _ P R O TO _ S I C K _ S T R E A M当作上面任何一个函数的协议参数投递出去。但系统不需要这个协议参数,因为传输目录中只有一个地址家族 A F _ I R D A条目。
指定 A F _ I R D A会造成默认使用这个传输条目。
6.2.6 套接字选项对 I r D A来说,大多数 S O _ s o c k e t选项都是没有意义的,只有 S O _ L I N G E R得到了特别的支持。 I r S o c k特有的套接字选项当然也得到了支持,不过只限于地址家族 A F _ I R D A套接字上。
我们将在第 9章全面论述这些选项,第 9章还对所有套接字选项及其参数进行了总结。
6.3 IPX/SPX
“互联网包交换” ( I P X)协议是一个常见协议,一般为承担 Novell NetWa r e客户机/服务器联网服务的计算机所用。 I P X提供两个进程间的无连接通信;因此,如果一个工作站发出一个数据包,该协议无法保证这个数据包会准确无误地投递到目标地点。如果应用程序需要数据投递保证,但仍坚持使用 I P X,它就会选用一个比 I P X高级的协议,比如说“顺序分组交换”
( S P X)和 SPX II协议,这两个协议中,S P X包通过 I P X发送。 Wi n s o c k为应用程序提供了在
Wi n d o w s平台上通过 I P X进行通信的能力(它们是 Windows 95,Windows 98,Windows NT以及 Windows 2000),但没有提供 Windows CE平台上通过 I P X通信的能力。
6.3.1 编址
I P X网络、网段是用 I P X路由器桥接在一起的。每个网段分配 4字节的唯一地址号。当更多的网段桥接在一起时,I P X路由器管理网段之间的通信,每个网段有唯一的网段号。连网时,
使用唯一的 6字节网段号,这个号也往往是转接器的物理地址。一个节点(也就是一台计算机)
一般有一个或多个通信进程用 I P X通信。 I P X用套接字号来区分一个节点上的通信。
要用 I P X进行 Wi n s o c k客户机或服务器通信,必须建立 S O C K A D D R _ I P X结构。该结构在
W s i p x,h头文件中定义,应用程序在包括 Winsock 2.h文件之后还必须包括该文件。 S O C K A D D R _
I P X结构如下定义:
s a _ f a m i l y字段应设为 A F _ I P X值,s a _ n e t n u m字段是 4字节的地址,代表 I P X网络上网段号,
s a _ n o d e n u m字段是 6字节的地址,代表节点计算机的物理地址,s a _ s o c k e t字段代表一个节点区分 I P X通信的套接字或接口。
6.3.2 创建套接字利用 I P X创建套接字提供了几种可能性。要打开 I P X套接字,调用带有地址家族 A F _ I P X、
套接字类型以及 N S P R O TO _ I P X协议的 s o c k e t函数或 W S A S o c k e t函数即可,过程如下:
112计计 第二部分 附 Winsock API 下载注意,第三个参数协议是必须指定的,而且不能为 0。这一点相当重要,因为该字段还可用于设置特定 I P X包的类型。
正如我们前面提到的那样,I P X利用数据报提供不可靠的无连接通信。如果一个应用需要可靠的无连接通信,可采用比 I P X高级的协议,比说 S P X和 SPX II。要做到这一点,把 s o c k e t
和 W S A S o c k e t调用的类型和协议字段分别设置成套接字类型 S O C K _ S E Q PA C K E T或
S O C K _ S T R E A M和协议字段 N S P R O TO _ S P X或 N S P R O TO_SPX II即可。
如果指定了 S O C K _ S T R E A M,系统就会把数据当作连续不断的字节流发送出去,没有消息边界,这类似于 T C P / I P中套接字的行为。另一方面,如果发送端发出 2 0 0 0个字节,在这
2 0 0 0个字节全部到达接收端之前,接收端是不会返回任何消息的。对 S P X和 SPX II来说,这是通过设置 S P X头中的消息结束位来完成的。指定 SOCK_ STREAM时,要注意这个位,
Winsock recv和 W S A R e c v调用在其收到这个位之前不会中止。如果指定 S O C K _ S T R E A M时没有注意到这个消息结束位,一旦接收端收到数据,r e c v就会中止,不管消息结束位设在哪里。
从发送端这一方来说(使用 S O C K _ S E Q PA C K E T类型),如果发送的数据包小于一个完整的数据包,消息结束位就会随这个包一起发送。如果发送的包大于一个完整的数据包,消息结束位就只设在最后发送的那个包中,而不是每个包都有。
1,绑定套接字
I P X应用通过 b i n d把本地地址和套接字关联在一起时,不要在 S O C K A D D R _ I P X结构中指定网络号和节点地址。 b i n d函数利用系统上可用的第一个 I P X网络接口来填充这些字段。如果一台计算机有多个网络接口(多址计算机),它就不必绑定特定的接口。 Windows 95、
Windows 98,Windows NT和 Windows 2000提供一个虚拟内部网,不管它直接连接的物理网络如何,该虚拟网中的每个接口都是可以抵达的。我们稍后将对内部网络编号进行详细论述。
应用成功绑定本地接口之后,便可利用下属代码段中的 g e t s o c k n a m e函数获得本地网络编号和节点编号的信息。
第 6章 计 地址家族和名字解析 计计 113下载
114计计 第二部分 附 Winsock API 下载
2,网络编号与内部网络编号网络编号(通常称作外部网络编号)用于标识 I P X中的网络段和 I P X报在网络段之间的路由选择。 Windows 95,Windows 98,Windows NT以及 Windows 2000平台特别突出了内部网络编号,这个内部网络编号用于内部路由选择和对网间网(几个网络桥接在一起构成)上的计算机进行唯一性标识。内部网络编号也称为“虚拟网号”,即内部网络编号对网间网中的另一个(虚拟的)网络段进行标识。因此,如果一台计算机正在运行 Windows 95,Windows 98、
Windows NT或 Windows 2000,若打算为它配置一个内部网络编号,N e t Wa r e服务器或 I P X路由器就会在自己与那台计算机的路由之间另增一次跳跃。
在多址计算机情形下,内部虚拟网络用于某一特定目的。应用程序绑定本地网络接口时,不应该指定本地接口信息,但需要把 S O C K A D D R _ I P X结构的 s a _ n e t n u m和 s a _ n o d e n u m这两个字段设置为 0。这是因为 I P X能够通过内部虚拟网络的使用,把一个数据包从任何一个外部网络路由到任何一个本地网络接口。比如,即使你的应用程序明显地绑定网络 A上的网络接口,而数据包却来自网络 B,内部网络编号就会使这个数据包在内部路由,这样,你的应用程序就收到这个数据包了。
3,通过 Wi n s o c k,设置 I P X数据包的类型在利用 N S P R O TO _ I P X建立套接字时,Wi n s o c k允许应用程序指定 I P X包的类型。 I P X包内的数据包类型字段表明这个 I P X包提供或请求的服务类型。在 N o v e l l网中,下面的 I P X包类型的定义是:
■ 0 1 h:路由信息协议( R I P)包。
■ 0 4 h:服务声明协议( S A P)包。
■ 0 5 h:顺序分组交换( S P X)包。
■ 11 h,N e t Ware Core协议( N C P)包。
■ 1 4 h,Novell NetBIOS的传输包。
要修改 I P X包类型,只须把 N S P R O TO_IPX + N指定为 socket API的协议参数,n表示数据包类型的编号。比如,要打开一个把包类型设为 0 4 h( S A P包)的 I P X套接字,可用下面的
s o c k e t调用:
4,名字解析大家可能知道,Wi n s o c k中的 I P X定址有些麻烦,因为必须提供构成地址的多字节的网络和节点编号。 I P X使应用程序可以通过用户友好名找到相应服务,以此通过 S A P协议获得 I P X
网络中的网络编号、节点编号和端口编号。正如我们将在第 1 0章看到的那样,Winsock 2利用
WSASetService API函数,提供了一个与协议无关的名字解析法。通过 S A P协议,I P X服务器应用可利用 W S A A e t S e r v i c e在用户友好名下注册它们正在监听的网络编号、节点编号和端口第 6章 计 地址家族和名字解析 计计 115下载编号。 Winsock 2还通过下面几个 A P I函数提供了另一个与协议无关的名字解析法,它们是:
W S A L o o k u p S e r v i c e B e g i n,W S A l o o k u p S e r v i c e N e x t和 W S A l o o k u p S e r v i c e E n d。
要执行自己的命名服务注册和查找,可以通过打开一个 I P X套接字并指定 S A P类型的方法来完成。打开套接字之后,便可开始向 I P X网络广播 S A P包,以便在网络上注册和定位服务。
这要求大家深入了解 S A P协议和掌握针对 IPX SAP包解码的编程方面的基本知识。
6.4 NetBIOS
N e t B I O S地址家族也是另一种可从 Wi n s o c k访问的协议家族。通过第 1章的 N e t B I O S讨论,
大家将进一步熟悉这里提到的许多主题和注意事项。从 Wi n s o c k开始的 N e t B I O S定址仍需要得知 N e t B I O S名和 L A N A编号。我们假定大家已看过第 1章中的这些小节,然后,继续深入通过
Wi n s o c k访问 N e t B I O S的特性。
注意 NetBIOS地址家族由 Winsock剖析,只能用于 Windows NT和 Windows 2000。不能用于 Windows 95,Windows 98和 Windows CE。
6.4.1 定址
N e t B I O S下机器的定址基础是 N e t B I O S名,这个我们已在第 1章中讲过。 N e t B I O S名有 1 6
个字符长,最后一个字符留给定义这个名属于哪类服务的限定字符用。 N e t B I O S名有两种类型:专有名和组名。专有名可只由整个网络上的一个进程注册。比如,一个基于会话的服务器将注册 F O O名,而打算和该服务器沟通的客户机则试着和 F O O连接。组名允许一组应用注册同一个名字,如此一来,注册了这个组名的所有进程都可收到发给这个名字的数据报。
Wi n s o c k中,N e t B I O S定址结构是在 W s a n e t b s,h中定义的,格式如下:
s n b _ f a m i l y字段指定这个结构的地址家族,它应该始终为 A F _ N E T B I O S。 s n b _ t y p e字段用于指定一个专有名或组名。下面的定义可用于这个 s n b _ t y p e字段:
最后,s n b _ n a m e字段就是事实上的 N e t B I O S名。
现在,大家已知道各字段的含义以及应该怎样设置它们了,下面设置的宏定义于头文件中,方便易行:
这个宏的第一个参数 _ s n b是此时正在填的 S O C K A D D R _ N B结构的地址。正如大家所见的那样,它自动把 s n b _ f a m i l y字段设为 A F _ N E T B I O S。而这个宏的 _ t y p e参数指定的是
N E T B I O S _ U N I Q U E _ N A M E或 N E T B I O S _ G R O U P _ N A M E。 _ n a m e参数是 N e t B I O S名。这个宏认定其长度至少是 N E T B I O S _ N A M E _ L E N G T H减 1,如果短于这一长度,它就会空中止。注意,s n b _ n a m e字段是用空格来预填的。最后,这个宏把 s n b _ n a m e字符串的第 1 6个字符设为
_ p o r t参数的值。
大家可看到,Wi n s o c k中 N e t B I O S名的结构是直接了当的,没有任何令人费解之处。名字解析是在悄然执行的,因此,它不像 T C P和 I r D A那样,在执行操作之前,不必把名字解析成物理地址。在考虑到依赖于多个协议实施 N e t B I O S,但各个协议都有自己的一套定址方案时,
这一点更为明显。下一章中,我们将通过在 Wi n s o c k中使用 N e t B I O S接口,向大家展示一个简单的客户机/服务器范例。
6.4.2 创建套接字创建套接字时,最重要的一点是 L A N A编号。就像使用原始 NetBIOS API那样,必须知道哪些 L A N A编号和你的应用有关。必须记住,N e t B I O S客户机和服务器要进行通信,必须有一个常用的传输协议,这样它们便可通过该协议进行监听或连接。创建 N e t B I O S套接字有两种方法。其一是像下面这样调用 s o c k e t或 W S A S o c k e t:
根据你需要的是一个无连接数据报,还是面向连接的会话套接字,W S A S o c k e t的 t y p e参数分别是 S O C K _ D G R A M和 S O C K _ S E Q PA C K E T(不能两个同时指定) 。第三个参数 p r o t o c o l,除非你必须将其取消,否则就是准备依据它来创建套接字的那个 L A N A编号。第四个参数是空值,
因为你此刻正在指定自己的参数,而不是正在使用 W S A P R O TO C O L _ I N F O结构。第五个参数没有用。最后,把 d w F l a g s参数设为 W S A _ F L A G _ O V E R L A P P E D;根据所有 W S A S o c k e t调用,
指定 W S A _ F L A G _ O V E R L A P P E D。
第一种套接字创建法的不足之处是必须知道从哪一个有效 L A N A编号着手。不幸的是,
Wi n s o c k目前没有妙方把所有有效 L A N A编号列举出来。备用 Wi n s o c k可利用 W S A E n u m P r o t o c o l s
把所有传输协议列举出来。当然,也可利用 N C B E N U M命令调用 N e t b i o s,从而获得有效的
L A N A编号。第 5章对如何调用 W S A E n u m P r o t o c o l s进行了说明。下面的实例列举了所有的传输协议,搜查到一个 N e t B I O S传输,并针对各个协议分别建立了套接字。
116计计 第二部分 附 Winsock API 下载在上面的伪代码中,我们列举了可用的传输协议,并通过它们对属于 A F _ N E T B I O S地址家族的协议进行反复查找。接下来,我们要检查套接字类型,这里要查找的是 S O C K _ S E Q PA C K E T
类型的条目。如需要数据报,就检查 S O C K _ D G R A M。如果找到的套接字类型和条目匹配,我们就有一个可以使用的 N e t B I O S传输协议了。如果还需要一个 L A N A编号,就选用 W S A P R O TO C O L S _I N F O
结构中 i P r o t o c o l字段的绝对值。这个 L A N A的 i P r o t o c o l字段是 0 x 8 0 0 0 0 0 0 0,因为 0是 Wi n s o c k为特殊用途保留的。变量 j将包含一个值,表示有效传输协议有多少个。
6.5 AppleTalk
Wi n s o c k中,对 A p p l e Ta l k的支持已发布一段时间了,但鲜为人知。如果不与苹果公司的
M A C机通信,你可能不会选择 A p p l e Ta l k协议。从某种程度上来说,A p p l e Ta l k与 N e t B I O S类似,
因为两者都是针对每一个进程来进行名字注册的。也就是说,要使特定的名字广为人知,服务器必须对这个名字进行注册。客户机再用这个名字与服务器建立连接。究其本质,
A p p l e Ta l k名比 N e t B I O S名更为复杂。下一小节,我们将讨论如何为网络上使用 A p p l e Ta l k协议的计算机进行定址。
6.5.1 定址
A p p l e Ta l k名实际上是以三个独立的名字为基础的:名、类型和区。每个名字的长度可达
3 2个字符。这个名字标识机器上的进程及其关联套接字。类型是区的子群机制。传统意义上,
区是一个网络,它是由物理定位于同一个循环上、使用 A p p l e Ta l k协议的计算机构成的。微软的 A p p l e Ta l k实施方案允许 Wi n d o w s兼容机对自己定位的默认区进行指定。多个网络可通过桥接联在一起。这些易记的名字分别映射一个套接字编号、一个节点编号和一个网络编号。在特定的类型和区内,A p p l e Ta l k名必须是独一无二的。这项要求由“名字绑定协议” ( N B P)
来执行,该协议将一次查询在网上广播,以便知道这个名字是否已使用。与此同时,
A p p l e Ta l k利用“路由表维护协议” ( RT M P),动态地对链接在一起的各个 A p p l e Ta l k网络的路由进行查找。
下一个结构提供了从 Wi n s o c k为 A p p l e Ta l k主机定址的基础:
第 6章 计 地址家族和名字解析 计计 117下载注意,这个地址结构中只有字符或短整型数,没有友好名。 S O C K A D D R _ AT结构被投入
b i n d,c o n n e c t和 W S A c o n n e c t之类的 Wi n s o c k调用中,但如果要转换易于理解的名字,必须要求网络系统先对这个名字进行解析或注册。这是分别通过 g e t s o c k o p t或 s e t s o c k o p t调用来完成的。
6.5.2 AppleTalk名的注册对一个服务器而言,如果它打算注册特定名字,以便客户机可以很容易地与之建立连接,
就要利用 S O _ R E G I S T E R _ N A M E选项来调用 s e t s o c k o p t函数。牵涉到 A p l p l e Ta l k名的所有套接字选项,都要使用 W S H _ N B P _ N A M E结构,它的格式如下:
许多类型(比如说 W S H _ R E G I S T E R _ N A M E,W S H _ D E R E G I S T E R _ N A M E和
W S H _ R E M O V E _ N A M E)都是在这个 W S H _ N B P _ N A M E结构的基础上定义的。使用哪个类型要根据具体情况而定,看你是查找名字呢,还是注册名字或删除名字。
下面的代码实例解释了如何注册 A p p l e Ta l k名。
118计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 119下载大家首先注意到的是 M Y _ Z O N E,M Y _ T Y P E和 M Y _ O B J E C T这三个字串。记住,
A p p l e Ta l k名是三级式的。注意,区是一个星号,*” 。这是区字段中所用的特殊字符,用来指定计算机处在“当前”区。接下来,我们建立一个隶属于 A p p l e Ta l k协议 A D S P的 S O C K _ S T R E A M
类型的套接字。这个套接字建立之后,有一个利用一个地址结构进行的 b i n d调用,这个地址结构中有一个置零 s a t _ s o c k e t字段和唯一设置的协议家族字段。这是非常重要的,因为它为发出请求的用户应用在网络上建立了一个端点。注意,虽然调用 b i n d允许你在网络上执行简单操作,但它本身不允许你的应用接受客户机发出的接入连接请求。要接受客户机连接,必须在网络上注册你自己的名字,这是下一步的工作。
注册 A p p l e Ta l k名很简单。把 S O L _ A P P L E TA L K当作,l e v e l”参数,S O _ R E G I S T E R _ N A M E
当作 o p t n a m e参数投递出去,便可调用 s e t s o c k o p t。后两个参数是一个指针,它指向我们的
W S H _ R E G I S T E R _ N A M E结构及其长度。如果调用 s e t s o c k o p t成功,我们的服务器名便得以成功注册。如果调用失败,所请求的名字大概已为他人所用。返回的 Wi n s o c k 错误是
W S A E A D D R I N U S E( 1 0 0 4 8或 0 x 0 2 7 4 0 h) 。注意,对同时面向数据报和面向流的 A p p l e Ta l k协议来说,想接收数据的进程必须注册一个名字,以便客户机可向它发送数据报或与之建立连接。
6.5.3 AppleTalk名的解析同等的客户机这一端,应用通常通过友好名来得知服务器,而且必须把这个友好名解析成 Wi n s o c k调用所用的网络、节点和套接字编号。这是通过 SO_LOOKUP_ NAME选项调用
g e t s o c k o p t函数来完成的。执行 A p p l e Ta l k名的查找依赖于 W S A _ L O O K U P _ N A M E结构。这个结构及其相关结构的格式如下:
在利用 S O _ L O O K U P _ N A M E选项调用 g e t s o c k o p t时,我们把一个缓冲造型当作 W S H _
L O O K U P _ N A M E结构投递出去,并在第一个 L o o k u p Tu p l e成员内填写 W S H _ N B P _ N A M E。调用成功后,g e t s o c k o p t返回一个 W S H _ N B P _ T U P L E元素组成的数组,其中包含那个 A p p l e Ta l k
名的物理地址信息。程序清单 6 - 1中包含了 A t a l k n m,c文件,该文件对如何查找 A p p l e Ta l k名进行了解释。除此以外,程序清单 6 - 1还展示了如何列出所有的“已找到的” A p p l e Ta l k区以及如何找到用户的默认区。区信息可通过 g e t s o c k o p t选项 SO_LOOKUP _ZONES和 S O _ L O O K U P _
M Y Z O N E来获得。
程序清单 6-1 AppleTa l k名和区的查找
120计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 121下载
122计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 123下载
124计计 第二部分 附 Winsock API 下载在使用许多 A p p l e Ta l k套接字选项时 — 比如 S O _ L O O K U P _ M Y Z O N E,S O _ L O O K U P _
Z O N E S以及 S O _ L O O K U P _ N A M E— 需要为 g e t s o c k o p t调用提供更大的字符缓冲。如果调用要求你提供一个结构的选项,这个结构必须在所供字符缓冲之首。如果调用 g e t s o c k o p t成功,
这个函数就把返回的数据放在所供结构之后的字符缓冲中。我们来看看程序清单 6 - 1中的
S O _ L O O K U P _ N A M E这一部分。变量 c L o o k u p B u ff e r是一个用于 g e t s o c k o p t调用中的简单字符数组。首先,我们把它造型成 P W S H _ L O O K U P _ N A M E,并在里面填入想查找的名字信息。
然后,把这个缓冲投入 g e t s o c k o p t,再根据返回的结果,增加字符指针 p Tu p l e B u ff e r,这样,
令其指向 W S H _ L O O K U P _ N A M E结构之后的那个字符。接下来,再把这个字符指针造型成一个 PWSH_NBP_TUPLE WSH变 量,因 为 查 找 A p p l e Ta l k名 调 用 返 回 的 数 据 是 一 个
W S H _ N B P _ T U P L E结构组成的数组。一旦有了正确的起始位置和字元组类型,就可大功告成了。关于 A p p l e Ta l k地址家族特有的各种套接字选项的详细资料,请参考第 9章。
6.5.4 创建套接字
A p p l e Ta l k可用于 Winsock 1.1及稍后的版本,因此可任选套接字创建例程。再次提醒大家注意,指定基层 A p p l e Ta l k协议的方式有两种。其一,可为自己需要的协议提供 A t a l k w h,h中的相应定义。其二,利用 W S A E n u m P r o t o c o l s,然后投递 W S A P R O TO C O L _ I N F O结构,便可列举协议了。至于直接用 s o c k e t或 W S A S o c k e t创建套接字时各 A p p l e Ta l k协议所需的参数,均可参见表 6 - 1。
表 6-1 AppleTa l k协议和参数协 议 地址家族 套接字类型 协议类型
MSAFD AppleTa l k [ A D S P ] S O C K _ R D M AT P R O TO _ A D S P
MSAFD AppleTa l k S O C K _ S T R E A M AT P R O TO _ A D S P
[ A D S P ] [ P s e u d o - S t r e a m ] A F _ A P P L E TA L K
MSAFD AppleTa l k [ PA P ] S O C K _ R D M AT P R O TO _ PA P
MSAFD AppleTa l k [ RT M P ] S O C K _ D G R A M D D P P R O TO _ RT M P
MSAFD AppleTalk [ZIP] S O C K _ D G R A M D D P P R O TO _ Z I P
6.6 ATM
异步传输模式( AT M)协议是目前已有的最新协议之一,Windows 98和 Windows 2000平台上的 Winsock 2均支持它。 AT M通常用于 L A N和 WA N上的高速联网,也用于各种类型的通信,比如说要求高速通信的语音、视频和数据等。一般说来,AT M利用网络上的虚拟连接
( V C)来提供服务质量( Q O S)保证。正如大家即将看到的那样,Wi n s o c k能够通过 AT M地址家族来使用 AT M网络上的虚拟连接。 AT M网络(如图 6 - 1所示)一般由通过交换机(它们将
AT M网络桥接在一起)连接的端点(或计算机)构成。
针对 AT M协议编程时,需要明白这几点。首先,AT M是一个媒体类型,而不是一个真正的协议。也就是说,AT M类似于直接在以太网上写入以太帧。和以太网一样,AT M协议没有提供流控制。它是一个面向连接的协议,要么提供消息模式,要么提供流模式。这还意味着第 6章 计 地址家族和名字解析 计计 125下载如果数据不能快速发送出去,发送应用则可能溢出本地缓冲。同样地,接收应用必须频繁投递收到的数据:否则,接收缓冲填满之时,任何一个另外接入的数据都可能被丢弃。如果你的应用需要流控制,方法之一是在 AT M上使用 I P协议(它只是运行于 AT M网络上的 I P协议) 。
这样一来,应用便紧跟在上面描述的 I P地址家族之后。当然,AT M的确提供了比 I P好的一些好处,比如说“根式多播方案” (第 1 2章将对此进行说明);然而,要根据自己的应用需要来决定最适合你的那种协议。
图 6-1 ATM网络
6.6.1 定址一个 AT M网络有两个网络接口:用户网络接口( U N I)和网络节点接口( N N I) 。 U N I接口是在终端和 AT M交换机之间建立的,而 N N I接口则是在两个交换机之间建立的。各个接口都有自己相关的通信协议,具体说明如下:
■ U N I信号协议 允许终端在一个终端和一个 AT M交换机之间发送设置和控制信息,从而在 AT M网络上建立通信。注意,这个协议只限于一个终端和一个 AT M交换机之间的传输,不能直接通过交换机在 AT M网络上传输。
■ N N I信号协议 允许 AT M交换机在两个交换机之间交流路由选择和控制信息。
若想通过 Wi n s o c k设置 AT M连接,那么我们只讨论 U N I信号协议中的特定信息元素。目前,
Windows 2000和 Windows 98( S P 1)上的 Wi n s o c k可支持 U N I信号协议 3,1版本。
Wi n s o c k允许客户机/服务器通过设置“服务访问点” ( S A P)应用在 AT M网络上进行通信。这是利用 ATM UNI信号协议设置“服务访问点”之后形成的连接来完成的。 AT M是一个面向连接的协议,要求端点为进行通信,在 AT M网络上建立虚拟连接。对 AT M网络上通信用的套接字接口而言,S A P只是允许 Wi n s o c k应用通过 S O C K A D D R _ AT M地址结构对它进行注册和标识。 S A P一旦建立,Wi n s o c k就利用 U N I信号协议,向 AT M网络发出调用,通过这种方式,
便用这个 S A P在 AT M网络上的 Wi n s o c k 客户机和服务器之间建立一个虚拟连接。
S O C K A D D R _ AT M结构的格式如下:
ATM
转换 ATM
转换
ATM
转换
ATM
转换
ATM
终端
ATM
终端
s a t m _ f a m i l y应该一直为 A F _ AT M。 s a t m _ n u m b e r字段利用其中一个基本 AT M定址方案——
E,1 6 4和“网络服务访问点” ( N S A P),将事实上的 AT M地址表示成一个 AT M _ A D D R E S S结构。
N S A P也表示,N A S P式的 AT M终端系统地址” ( A E S A) 。 AT M _ A D D R E S S结构的格式如下:
A d d r e s s Ty p e字段定义特定的定址方案。如果是 E,1 6 4定址方案,这个字段就是 AT M _ E 1 6 4;
若是 N S A P式的定址方案,该字段就是 AT M _ N S A P。除此以外,在应用打算把套接字和一个
S A P绑定在一起时,还可将 A d d r e s s Ty p e字段设为表 6 - 2中定义的其他值。本章稍后将对此进行详细讨论。 N u m o f D i g i t s字段应该一直设为 AT M _ A D D R _ S I Z E。 A d d r字段表示事实上的 AT M
2 0字节的 E,1 6 4或 N A S P地址。
S O C K A D D R _ AT M结构的 s a t m _ b l l i和 s a t m _ b h l i这两个字段分别代表 AT M信号协议 中的
“宽带基层信息” ( B L L I)和“宽带高层信息” ( B L L I) 。一般说来,这些结构用于对 AT M连接上运行的协议堆栈进行标识。对几个 B L L I和 B H I L值已知组合的说明参见 ATM Form/ I E T F
(互联网工程任务组)文档(这些值的特定组合用于标识 AT M网络上的 L A N仿真,而另一种组合则用于标识 AT M网络上的原始 I P,如此等等) 。这些结构中的字段值都列在 ATM UNI 3.1标准一书中。 ATM Form/ I E T F文档都可在网上地址 h t t p,/ / w w w,i e t f,o rg找到。
表 6-2 AT M套接字地址类型
ATM_ADDRESS AddressTy p e设置 地 址 类 型
AT M _ E 1 6 4 E,1 6 4地址,与 S A P连接时使用
AT M _ N S A P N S A P式的 AT M终端系统地址( A E S A),与 S A P连接时使用
S A P _ F I E L D _ A N Y _ A E S A _ S E L N S A P式的 AT M终端系统地址,带有通配的八个选择符。
在绑定套接字和 S A P时使用
S A P _ F I E L D _ A N Y _ A E S A _ R E S T N S A P式的终端系统地址,不包括通配的八个选择符,
但其他的所有八个字符都有。在绑定套接字和 S A P时使用
B H L I和 B L L I数据结构的格式如下:
126计计 第二部分 附 Winsock API 下载关于这些字段的定义和用法,不在本书讨论之列。如果一个应用只想在 AT M网络上建立
Wi n s o c k通信,就应该把 B H L I和 B L L I结构中的下列字段设为 S A P _ F I E L D _ A B S E N T值:
■ AT M _ B L L I— 第二层协议。
■ AT M _ B L L I— 第三层协议。
■ AT M _ B H L I— 高层信息类型( H i g h L a y e r I n f o Ty p e) 。
在上述字段被设为这个值时,不再使用这两个结构中的其他字段。下面的伪代码演示了一个应用如何用 S O C K A D D R _ AT M结构为 N S A P地址设置 S A P:
AT M地址一般表示成一个十六进制的 A S C I I 字符串,由 4 0个字符组成,与组成
AT M _ A D D R E S S结构 N S A P式或 E,1 6 4地址的 2 0个字节相对应。比如,AT M _ N S A P式的地址可能像这样:
把这个字串转换成一个 2 0字节的地址相当麻烦。然而,Wi n s o c k提供了一个与协议无关的
A P I函数,W S A S t r i n g To A d d r e s s,利用它,便可把一个 4 0个字符的 AT M十六进制 A S C I I字串转换成一个 AT M _ A D D R E S S结构。我们将在本章最后着重讲一讲这个 A P I函数。把一个十六进制 A S C I I字串转换成十六进制(二进制)格式的另一种方法是利用程序清单 6 - 2中定义的 A t o H
函数。该函数不属于 Wi n s o c k。但是,和前一个函数比较起来,它更容易开发,大家可在第 7
章中的实例中看到它。
程序清单 6-2 用于转换 AT M十六进制字串的函数第 6章 计 地址家族和名字解析 计计 127下载
6.6.2 创建套接字
AT M中,应用只能建立面向连接的套接字,因为 AT M只允许通过虚拟连接进行的通信。
因此,数据的传输的形式是字节流或采用面向消息的形式。要利用 AT M协议打开一个套接字,
先通过地址家族 A F _ AT M和套接字类型 S O C K _ R AW调用 s o c k e t函数或 W S A S o c k e t函数,然后再把协议字段设为 AT M P R O TO _ A A L 5即可。比如:
默认状态下,打开套接字(比如上面这个例子)建立一个面向流的 AT M套接字。 Wi n d o w s
还有一个富有特色的 AT M提供者,可执行面向消息的数据传输。使用这个面向消息的提供者要求用户为 W S A S函数显式指定原始 AT M协议提供者,这是利用 W S A P R O TO C O L _ I N F O结构完成的(关于这一结构,我们曾在第 5章详细讲过) 。这一点是必须的,因为 s o c k e t和 W S A S o c k e t
这两个调用中的三个元素(地址家族、套接字类型和协议)均和 Wi n s o c k中可以使用的每一个
128计计 第二部分 附 Winsock API 下载
AT M协议提供者相符。默认状态下,Wi n s o c k会返回与这三个属性相符的协议条目,并把这个协议条目标注成默认设置(在面向流的提供者情形下如此) 。下面的伪代码将演示如何获得
AT M面向消息协议提供者以及如何建立一个套接字:
6.6.3 把套接字和 SAP绑定在一起事实上,AT M地址是相当复杂的,因为它们由 2 0个字节组成,其中包含许多信息元素。
除了最后一个字节外,这些元素的所有其他字节,Wi n s o c k程序员均不用下功夫去记。 N S A P
式地址和 E,1 6 4地址中的最后一个字节均代表一个特定的选择符值,该值唯一允许应用定义和指定端点上特定的 S A P。正如我们前面指出的那样,Wi n s o c k利用 S A P建立 AT M网络上的通信。
Wi n s o c k应用打算在 AT M网络上进行通信时,服务器应用必须在一个端点上注册一个 S A P,
并等待客户机应用根据已注册的 S A P接入。对客户机应用来说,这只包括通过 AT M _ E 1 6 4或
AT M _ N S A P地址类型设置 S O C K A D D R _ AT M结构和提供与服务器 S A P关联在一起的那个 AT M
地址。要建立一个用于监听连接的套接字,应用必须先为指定的 A F _ AT M地址家族建立一个套接字。这个套接字一旦建立,应用就必须像表 6 - 2中定义的那样,利用 S A P _ F I E L D _ A N Y _
A E S A _ S E L,S A P _ F I E L D _ A N Y _ A E S A _ R E S T,AT M _ E 1 6 4或 AT M _ N S A P地址类型来定义
S O C K A D D R _ AT M结构。对 AT M套接字而言,应用一旦调用 Wi n s o c k的 bind API函数(我们将在第 7章对该函数进行讲述),就会建立一个 S A P,这些地址类型对 Wi n s o c k在端点上建立 S A P
的方式进行了定义。
S A P _ F I E L D _ A N Y _ A E S A _ S E L地址类型要求 Wi n s o c k建立一个能对任何一种 AT M Wi n s o c k
连接进行监听的 S A P,这就是通常所说的通配 AT M地址和选择符。这意味着监听连接的这个端点只能绑定一个套接字 — 另一个套接字打算与这个地址类型绑定在一起,就会失败,并出现这样的 Wi n s o c k错误 W S A E A D D R I N U S E。然而,你也可以将另一个套接字和指定选择符上的端点显式绑定在一起。而显式和端点上的指定选择符绑定在一起的 S A P,则可用地址类型 S A P _ F I E L D _ A N Y _ A E S A _ R E S T来建立。这就是人们常说的只有 AT M地址,而没有选择符的“通配” 。对端点上的一个指定选择符而言,一次只能绑定一个套接字,否则 b i n d调用就会失败,并返回错误 W S A E A D D R I N U S E。在使用 S A P _ F E I L D _ A N Y _ A E S A _ S E L类型时,应该在 AT M _ A D D R E S S结构中指定一个均由零组成的 AT M地址。如果使用的是 S A P _ F I E L D _
A N Y _ A E S A _ R E S T,就应该把这个 AT M地址的前 1 9个字节指定为 0,最后一个字节应该是准第 6章 计 地址家族和名字解析 计计 129下载备使用的选择符的编号。
和显式选择符( S A P _ F I E L D _ A N Y _ A E S A _ R E S T)绑定在一起的套接字优先于和通配选择符( S A P _ F I E L D _ A N Y _ A E S A _ S E L)绑定在一起的套接字。连接时,系统会优先采用和显式选择符( S A P _ F I E L D _ A N Y _ A E S A _ R E S T)或显式接口( AT M _ N S A P和 AT M _ E 1 6 4)绑定在一起的套接字(也就是说,如果一个连接接入套接字显式监听的指定端点和选择符,这个套接字就会获得连接) 。只有在无显式绑定套接字可用的情况下,才会用通配选择符套接字来获得连接。第 7章将进一步说明如何设置一个套接字,使其监听 S A P上的连接。
最后,可通过一个名为 A t m a d m,e x e实用程序获得所有的 AT M地址和端点上虚拟连接信息。
在开发 AT M应用程序和需要了解端点上哪些接口可用时,这个实例程序相当有用。下面表 6 - 3
中列出的命令行选项都可用。
表 6-3 命令行选项参数 说 明
- c 列出所有的连接(指的是虚伪连接,V C) 。列出远程地址和本地接口
- a 列出所有已注册的地址(比如说所有的本地 AT M接口及其地址)
- s 打印特性(当前调用次数,收到或发出的传信和 I L M I包数,等等)
6.6.4 名字解析目前,尚且没有命名提供者可用于 Wi n s o c k下的 AT M协议。因此,不幸的便是要求应用对这个长达 2 0个字节的 AT M地址进行指定,以便建立 AT M网络上的套接字通信。第 1 0章将讨论
Windows 2000域名空间(一般用于对带有友好服务名的 AT M地址进行注册) 。
6.7 Winsock 2支持的其他函数
Winsock 2提供了两个有用的支持函数,它们是 W S A A d d r e s s To S t r i n g和 W S A S t r i n g To A d d r e s s。
这两个函数提供了一个与协议无关的转换方法,可以把 S O C K A D D R结构转换成一个格式化的字符串,反之亦然。由于这两个函数都是与协议无关的,所以它们要求传输协议能支持字串转换。目前,它们只能用于 A F _ I N E T和 A F _ AT M这两个地址家族。 W S A A d d r e s s To S t r i n g函数的定义如下:
l p s a A d d r e s s参数代表特定协议(其中包括即将转换成字串的那个地址)的 S O C K A D D R结构。
这个 S O C K A D D R结构的长度则由 d w A d d r e s s L e n g t h参数指定。不同的协议,其长度也不相同。
l p P r o t o c o l I n f o参数是可选的,表示协议提供者。协议提供者可通过 WSAEnumProtocols API函数获得,参见第 5章。如果指定了 N U L L,对这个函数的调用就会采用第一个协议(它支持
l p s a A d d r e s s中指定的协议家族)的提供者。 l p s z A d d r e s s S t r i n g参数是一个缓冲,它收到的是易于理解的地址字串。 l p d w A d d r e s s S t r i n g L e n g t h参数代表 l p s z A d d r e s s S t r i n g的长度。根据结果,它返
130计计 第二部分 附 Winsock API 下载第 6章 计 地址家族和名字解析 计计 131下载回实际复制到 l p s z A d d r e s s S t r i n g中的字串长度。如果提供的缓冲不够大,这个函数调用就会失败,
并出现错误 W S A E FA U LT,而 l p d w A d d r e s s S t r i n g L e n g t h参数也会根据所需要的字节长度而更新。
相反地,W S A S t r i n g ToAddress API函数采用易于理解的地址串,并将它转换成一个
S O C K A D D R结构。 W S A S t r i n g To A d d r e s s的定义如下:
A d d r e s s S t r i n g参数是一个易于理解的地址串。表 6 - 4对该字串的格式进行了说明。
表 6-4 地址串的格式地址家族 字串格式
I P X X X,X X X,X X X,X X X,Y— X代表 I P地址串中的一组八字符,Y则表示端口号
AT M N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N— 4 0个 N
表示一个以十六进制表示的、由 2 0个字节组成的 AT M地址
A d d r e s s f a m i l y参数代表 A d d r e s s S t r i n g参数的地址家族类型。 l p P r o t o c o l I n f o参数是可选的,
代表一个协议提供者。如果把这个参数设为 N U L L,Wi n s o c k就会在第一个可用的协议提供者中进行搜索,查找 A d d r e s s f a m i l y参数所指定地址家族类型。如果想选定某个特定的协议提供者,WSAEnumProtocol API函数就可为你提供一个列表,已安装在系统中、可用的协议提供者都列在上面。 A d d r e s s缓冲参数选择的是收到信息的、地址串中的 S O C K A D D R结构。
l p A d d r e s s L e n g t h参数代表所生成的 S O C K A D D R结构的长度。
6.8 小结这一章论述了 Wi n s o c k支持的协议地址家族,说明了各个家族特有的定址属性。针对每个地址家族,我们还讨论了如何创建套接字和如何设置套接字地址结构,以便开始通过协议进行通信。下一章,我们将描述适用于 Wi n s o c k的基本通信技术,并把它们应用到本章讨论的所有地址家族上。