论坛: 编程破解 标题: Windows Sockets 规范及应用(第六章 Windows Socket 2的扩展特性) 复制本贴地址    
作者: xiaoxingchi [xiaoxingchi]    论坛用户   登录
第六章 Windows Socket 2的扩展特性
这一章将讨论从Windows Sockets 1.1到Windows Socket 2的主要变动。

6.1 同时使用多个传输协议
为了用户能够同时使用多个传输协议,在Windows Socket 2中,结构有所改变。在Windows Sockets 1.1中,软件开发商所提供的DLL实现了Windows Sockets的API和TCP/IP协议栈。Windows Sockets DLL和底层协议栈的接口是唯一而且独占的。Windows Socket 2改变了这种模型:它定义了一个Windows Sockets DLL和底层协议栈间的标准服务提供接口(SPI)。这使得一个Windows Sockets DLL能够同时访问不同软件开发商的多个底层协议栈。此外,Windows Sockets 2并不象Windows Sockets 1.1仅支持TCP/IP协议栈。与Windows开放系统结构(WOSA)兼容的Windows Sockets 2的结构如下图:


图6-1:Windows Socket 2开放系统结构图

注意:16位的Windows Sockets 2应用程序应使用WS2-16.DLL,而32位的Windows Sockets 2应用程序应使用WS2-32.DLL。但今后,为了简单起见,它们将都使用WINSOCK.DLL。这并不会造成任何问题,因为在它们之间并没有任何语法上的区别。
由于以上的结构,现在已没有必要每个协议栈开发商都提供它们自己的WINSOCK.DLL(甚至这样做也不是期望的)。因为任何一个WINSOCK.DLL能够在所有协议栈上工作。因此,WINSOCK.DLL可以被看作是一个操作系统组件。Microsoft将在Windows 95和Windows NT上提供一个32位的WINSOCK.DLL。Intel公司目前正在打算提供Windows 3.1和Windows 3.11上的Windows Sockets 2兼容的16位WINSOCK.DLL。

6.2 与Windows Socket 1.1应用程序的向后兼容性 
Windows Socket 2与Windows Sockets 1.1在两个基础上向后兼容:源码和二进制代码。这就实现了Windows Sockets应用程序和任何版本的Windows Sockets实现之间的最大的互操作性,而且也减少了Windows Sockets应用程序使用者,网络协议栈提供者和服务提供者的许多痛苦。现有的Windows Sockets 1.1兼容的应用程序可以在Windows Sockets 2实现上不加修改的运行,只要有一个TCP/IP协议栈被安装。

6.2.1 源码的兼容性
Windows Sockets 2中的源码兼容性意味着所有的Windows Sockets 1.1版的API在Windows Sockets 2中都被保留了下来。这意味着现有的Windows Sockets 1.1应用程序的原程序可以被简单的移植到Windows Sockets 2系统上运行。程序员需要做的只是包含新的头文件-WINSOCK2.H和简单的与合适的Windows Sockets 2函数库的连接。应用程序开发者应该把这种工作看作是完全转向Windows Sockets 2的第一步,因为有许多方式可以使用Windows Sockets 2中的新函数来提高原来的Windows Sockets 1.1应用程序的运行性能。

6.2.2 二进制兼容性
在设计Windows Sockets 2时的一个主要目标就是使得现有的Windows Sockets 1.1应用程序在二进制级别上能够不加修改的应用于Windows Sockets 2之上。由于Windows Sockets 1.1是基于TCP/IP上的,二进制兼容性就要求Windows Sockets 2系统提供基于TCP/IP上的Windows Sockets 2的传输和名字解析服务。为了Windows Sockets 1.1应用程序能在这种意义上运行,Windows Sockets 2系统提供了一个附加的组件-Windows Sockets 1.1的DLL。Windows Sockets 2安装时的提示保证了在终端机用户引进Windows Sockets 2系统时不会对已有的Windows Sockets软件环境有任何影响。


图6-2:与Windows Sockets 1.1二进制兼容性结构图

一个完全的Windows Sockets 1.1二进制兼容的必要的前提是在系统上已经安装了至少一个TCP/IP协议栈并且在Windows Sockets 2中做了注册。Windows Sockets 1.1目前通过WSAData结构中的某些元素来得到关于底层TCP/IP协议栈的信息(例如通过WSAStartup()函数调用),这些信息包括iMaxSockets,iMaxUdpDg和IPVendorInfo。但是在Windows Sockets 2中,应用程序应该知道忽略这些信息,因为这些值不能统一地适用于所有协议栈。不过DLL必须仍然提供这些值以免破坏Windows Sockets 1.1的应用程序。这些信息只能从(因此也只能应用于)缺省的TCP/IP服务提供者得到。缺省的TCP/IP服务提供者是由WSAEnumProtocols()调用返回的PROTOCOL_INFO结构缓冲区的第一条TCP/IP协议栈。

6.3 在Windows Sockets中注册传输协议
要使Windows Sockets能够利用一个传输协议,该传输协议必须在系统上安装并且在Windows Sockets中注册。Windows Sockets 2的DLL包含了一组API来完成这个注册过程。这个注册过程包括建立一个新的注册和取消一个已有的注册。在建立新的注册时,调用者(假设是协议栈开发商的安装程序)必须提供一组或多组完整的关于协议的信息,这些信息将被用来填充PROTOCOL_INFO结构。

6.3.1 使用多个协议
一个应用程序可以通过WSAEnumProtocols()功能调用来得到目前有多少个传输协议可以使用,并且得到与每个传输协议相关的信息,这些信息包含在PROTOCOL_INFO结构中。然而,某些传输协议可能表现出多种行为。例如SPX是基于消息的(发送者发送的消息的边界在网络上被保留了),但是接收的一方可以选择忽略这些边界并把套接口作为一个字节流来对待。这样就很合理地导致了SPX有两个不同的PROTOCOL_INFO结构条目,每一个条目对应了一种行为。
在Windows Sockets 1中仅有一个地址族(AF_INET),它包含了数量不多的一些众所周知的套接口类型和协议标识符。这在Windows Sockets 2中已经有所改变。除了现有的地址族,套接口类型和协议标识符为了兼容性原因被保留以外,Windows Sockets 2加入了许多唯一的但是可能并不为大家所知的地址族,套接口类型和协议标识符。不为大家所知并不意味着会对应用程序开发造成问题,因为一个企图做成协议无关的应用程序应该在对自身合适的基础上选择协议而不应该依赖于某个分配给它的特定的套接口类型或协议类型值。PROTOCOL_INFO结构中包含的通讯性质指明了协议的合适性(例如:基于消息的对应于基于字节流的,可靠的对应于不可靠的,等等)。基于合适性原则选取协议而不使用某个特定的协议名和套接口类型。
对于客户机/服务器模型,服务器一端的应用程序最好能够在所有合适的传输协议上建立监听套接口。这样,客户机一端的应用程序就可以通过任何合适的传输协议来与服务器一端的应用程序建立连接。这样做可以使得一个客户机应用程序易于移植。例如一台运行于LAN上的台式机的客户机应用程序在转到运行于无线网上的笔记本计算机时就不用作任何改变。

6.3.2 select()函数应用中关于多个服务提供者的限制
在Windows Sockets 2中,函数select()使用FD_SET仅能应用于和单个服务提供者相连的套接口。但是这并不限制一个应用程序使用多个服务提供者打开多个套接口。如果应用程序开发者喜欢使用非阻塞方式编程,那么可以使用WSAAsyncSelect()函数。由于该函数需要一个套接口描述字作为输入参数,那么与该套接口相连的服务提供者是很重要的。如果一个应用程序需要在一组跨越多个服务提供者的套接口上使用带有阻塞语法的函数,那么应该使用WSAWaitForMultipleEvents()函数。应用程序也可以使用WSAEventSelect()函数。该函数允许应用程序把FD_XXX网络事件和一个事件对象相连接,并且在该事件对象中处理网络事件(这一模式将在下文讨论)。

6.4 协议无关的名字解析
Windows Sockets 2包含了应用程序可以使用的多种标准化的网络名字服务。Windows Sockets 2应用程序并不需要理解与名字服务相关的许多迥异的接口(例如DNS,NIS,X.5000,SAP等等)。本书的4.2介绍了这一主题,并对API做了详细介绍。

6.5 重叠I/O和事件对象
Windows Sockets 2引入了重叠I/O的概念并且要求所有的传输协议提供者都支持这一功能。重叠I/O仅能在由WSASocket()函数打开的套接口上使用(使用WSA_FLAG_OVERLAPPED标记)。这种方式的使用将采用Win32建立的模型。
对于接收,应用程序使用WSARecv()函数或WSARecvFrom()函数来提供存放接收数据的缓冲区。如果数据在网络接收以前,应用程序已经提供了一个或多个数据缓冲区,那么接收的数据就可以立即被存放进用户缓冲区。这样可以省去使用recv()函数和recvfrom()函数时需要进行的拷贝工作。如果在应用程序提供数据缓冲区时已经有数据到来,那么接收的数据将被立即拷贝进用户缓冲区。如果数据到来时,应用程序没有提供接收缓冲区,那么网络将回到我们熟悉的同步操作方式-传送来的数据将被存放进内部缓冲区,直到应用程序发出了接收调用并且提供了接收缓冲区,这时接收的数据就被拷贝进接收缓冲区。这种做法会有一个例外:就是当应用程序使用setsockopt()函数把接收缓冲区长度置为了0。在这种情况下,对于可靠传输协议,只有在应用程序提供了接收数据缓冲区后,数据才会被接收;而对于不可靠传输协议,数据将会丢失。
对于发送的一方,应用程序使用WSASend()函数或WSASendTo()函数提供一个指向已填充的数据缓冲区的指针。应用程序不应在网络使用完该缓冲区的数据以前以任何方式破坏该缓冲区的数据。
重叠发送和接收调用会立即返回。如果返回值是0,那么表明了I/O操作已经完成,对应的完成指示也已经可以得到。如果返回值是SOCKET_ERROR,并且错误代码是WSA_IO_PENDING,那么表明重叠操作已经被成功地初始化,今后发送缓冲区被用完或者接收缓冲区被填满时,将会有完成指示。任何其他的错误代码表明了初始化没有成功,今后也不会有什么完成指示。
发送操作和接收操作都可以被重叠使用。接收函数可以被多次调用,发出接收缓冲区,准备接收到来的数据。发送函数也可以被多次调用,组成一个发送缓冲区队列。要注意的是,应用程序可以通过按顺序提供发送缓冲区来确保一系列重叠发送操作的顺序,但是对应的完成指示有可能是按照另外的顺序排列的。同样的,在接收数据的一方,缓冲区是按照被提供的顺序填充的,但是完成指示也可能按照另外的顺序排列。
WSAIoctl()函数(ioctolsocket()函数的增强版本)还可以使用重叠I/O操作的延迟完成特性。 6.5.1 事件对象
重叠I/O概念的引入需要建立一个机制使得应用程序能够正确的把发送和接收事件与今后它们完成时的指示相连接。在Windows Sockets 2中,这一点是通过事件对象实现的,它采用了Win32事件的模型。Windows Sockets事件对象是一个相当简单的结构,它可以被创建,关闭,设置,清除,等待和检查。它们的主要用处是使得应用程序能够阻塞并等待直到一个或多个事件对象被设置。
应用程序可以使用WSACreateEvent()函数来得到一个事件对象句柄,这个句柄可以作为以后的重叠发送和接收函数的输入参数(WSASend(),WSASendTo(),WSARecv(),WSARecvFrom())。事件对象在创建时被清除,在相关的重叠I/O操作完成时由传输协议提供者设置(或者成功,或者出错)。每个被WSACreateEvent()函数创建的事件对象都必须有对应的WSACloseEvent()函数释放它。
WSAEventSelect()函数把一个或多个FD_XXX网络事件与一个事件对象连接。这将在2.6中讨论。
在32位环境中,与事件对象相关的函数,包括WSACreateEvent(),WSACloseEvent(),WSASetEvent(),WSAResetEvent(),WSAWaitForMultipleEvent()和WSAGetOverlappedResult(),都被直接映射到对应的Win32函数,例如没有WSA前缀的同名函数。

6.5.2 接收操作完成指示
为了提供给应用程序适当的灵活性,Windows Sockets 2为接收操作完成指示提供了多个选项。它们包括:等待(阻塞)事件对象,检查事件对象和套接口I/O完成例程。

6.5.2.1 阻塞并且等待完成指示。
应用程序可以使用WSAWaitForMultipleEvents()函数来选择阻塞程序直到一个或多个事件对象被设置。在Win16实现中,这种方式将使用一个阻塞钩子,就象在标准的阻塞套接口操作时一样。在Win32实现中,进程或线程会被真正地阻塞。因为Windows Sockets 2事件对象被实现成Win32事件,所以Win32函数WaitForMultipleObjects()也可以使用。这在线程需要阻塞套接口和非套接口事件时将会非常有用处。 6.5.2.2 检查完成指示
应用程序如果不希望使用阻塞方式,它可以使用WSAGetOverlappedResults()函数来检查与某个特定的事件对象相连的完成状态。该函数检查重叠操作是否完成,如果完成的话,处理重叠操作的出错信息,使得该信息在WSAGetLastError()函数调用时可以得到。

6.5.2.3 使用套接口I/O操作完成例程
所有的用来初始化重叠I/O操作的函数(WSASend(),WSASentTo(),WSARecv(),WSARecvFrom())都把lpCompletionRoutine作为输入参数。这是一个应用程序定义的函数指针,在重叠I/O操作完成时可以被调用。 
在Win16环境中,回调函数有可能在VMM环境(有时也被称作中断环境)下被激活。传送对时间要求较高的数据(例如视频或音频数据)在这种低延时,占先方式下接受这种指示会很方便。但是应用程序必须知道,在这种特殊情况下,只要很少一部分运行时和Windows库函数可以被调用。作为一条规则,应用程序必须把自己限制在一套Windows文挡说明的在一个多媒体定时回调函数中可以被安全调用的运行时函数库。
在Windows 95和Windows NT中,完成例程与Win32文件I/O完成例程遵循着同样的规则。在所有的环境中,传输协议允许应用程序以完成例程的方式唤起发送和接收操作,而且保证对于给定的一个套接口,I/O完成例程不会嵌套。这就允许了在一个占先的环境中进行对时间敏感的数据的传送。

6.5.3 WSAOVERLAPPED的细节
WSAOVERLAPPED结构提供了一个重叠I/O操作的初始化和它将来的如何被完成之间的通讯媒体。WSAOVERLAPPED结构被设计成与Win32中的OVERLAPPED结构兼容:
typedef struct WSAOVERLAPPED {
DWORD Internal; // reserved
DWORD InternalHigh; // reserved
DWORD Offset; // ignored
DWORD OffsetHigh; // ignored
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;

Internal 这一个保留的域是由重叠I/O实现的实体内部使用的。对于使用类文件方式创建套接口的传输服务提供者,这一域是被底层的操作系统使用的;对于其他的传输服务提供者(那些创建伪句柄的),可以视需要使用这个域。

InternalHigh 这一个保留的域是由重叠I/O实现的实体内部使用的。对于使用类文件方式创建套接口的传输服务提供者,这一域是被底层的操作系统使用的;对于其他的传输服务提供者(那些创建伪句柄的),可以视需要使用这个域。

Offset 由于套接口没有文件偏移量的概念,应用程序可以视需要使用这个域。

OffsetHigh 由于套接口没有文件偏移量的概念,应用程序可以视需要使用这个域。

hEvent 如果一个重叠的I/O操作在被调用时没有使用I/O操作完成例程(lpCompletionRoutine为空指针),那么这个域必须包含一个有效的WSAEVENT对象的句柄,否则(lpCompletionRoutine不为空指针),应用程序可以视需要使用这个域。

6.6 使用事件对象异步通知
为了适应一些应用程序例如精灵程序或者某些没有用户界面的服务程序(因此不使用窗口句柄),Windows Socket 2提供了WSAEventSelect()函数和WSAEnumNetworkEvents()函数。WSAEventSelect()函数和WSAAyncSelect()函数很类似,区别仅在于当一个FD_XXX网络事件发生时,WSAEventSelect()函数将导致一个应用程序指定的事件对象被设置,而WSAAyncSelect()将导致一条Windows消息被发送(例如FD_READ,FD_WRITE等等)。
此外,传输服务提供者会记住每个特定的FD_XXX网络事件的发生。应用程序可以调用WSAEnumNetworkEvents()函数把目前的网络事件记忆拷贝到应用程序提供的缓冲区中,并且自动清除网络事件记忆。如果需要,应用程序还可以把某个特定的事件对象和网络事件记忆一起清除。

6.7 服务的质量(QOS)
Windows Sockets 2中的QOS机制是从Craig Partridge在RFC 1363中描述的流规格引入的。这一概念可以大致描述如下:
流规格描述了一个网络上单向数据流的性质的集合。应用程序可以在调用WSAConnect()函数发出连接请求或者使用WSAIoctl()函数等其他QOS命令时,把一对流规格和一个套接口连接(一个规范对应了一个方向)。流规格以参数方式声明了应用程序所要求的服务的级别,并且为应用程序适应不同的网络条件提供了一套反馈机制-如果应用程序要求的服务级别不能达到,应用程序是否愿意松动它的要求。
Windows Sockets 2中QOS的使用模型如下:
对于基于连接的传输服务,应用程序可以很方便的在使用WSAConnect()函数提出连接请求时规定它所要求的服务质量(QOS)。要注意的是:如果应用程序在调用WSAConnect()时QOS参数不为空,那么对于基于连接的套接口,任何预先设置的QOS都会被覆盖。如果WSAConnect()函数成功返回,应用程序就会知道它所要求的QOS已经被网络接受,那么应用程序就可以随意的使用这个套接口进行数据交换。如果连接操作由于资源有限而失败,应用程序应该适当地降低它所要求的服务质量或者干脆就放弃操作。
在每次连接企图之后(不论成功与否),传输服务提供者都会更新flow_spec结构,以便尽可能地指明目前的网络条件。如果应用程序所要求的服务质量仅仅包含了一些传输服务提供者必须满足的缺省值,那么这种更新会是很有用处的。应用程序可以利用这些关于当前网络条件的信息来指导自己使用网络,例如今后的QOS要求。然而应用程序应该注意的是,传输服务提供者在不断更新的flow_spec结构中提供的信息仅仅是一个参考,它们只不过是粗略的估计。应用程序应该很小心的解释这些数据。
无连接的套接口也可以使用WSAConnect()函数为一个指定的通讯规定特定的QOS级别。WSAIoctl()函数也可以用来规定初始的QOS要求,或者用来今后的QOS协商。
即使是一个流规格已经建立,网络的情况也有可能改变,或者通讯的一方可能提出了QOS重协商的要求,这将导致可以得到的服务级别的降低或者提高。Windows Sockets 2引入了一个通知机制。它使用了一般的WS通知方式(FD_QOS和FD_GROUP_QOS事件)来告诉应用程序QOS级别已经改变了。一般服务提供者只在当前的服务级别和上一次报告有很大区别(通常是逆向的),并且有可能会影响到应用程序时才发出FD_QOS/FD_GROUP_QOS通知。应用程序应该使用WSAIoctl()函数来得到当前的状态并且检查服务等级的那些方面有了变化。如果当前的QOS级别是不可接受的,应用程序应该调整自己以去适应当前的状态,试图重新协商或者关闭套接口。 
Windows Sockets 2推荐的流规格把QOS特性划分为如下几个方面:
1. 源通讯描述:应用程序的通讯事件以什么方式被送入网络。
2. 延时性:最大延时和可接受的延时变化。
3. 需要保证的服务级别:应用程序是否要求对服务质量的绝对保证。
4. 费用:这一项是为将来可以决定有意义的费用时保留的。
5. 服务提供者特定的参数:流规格可以根据具体的提供者扩展。

6.8 套接口组
Windows Sockets 2引入了一个所谓套接口组的概念。它允许应用程序(或者一组共同工作的应用程序)通知底层的服务提供者一组特定的套接口是相关的,它们享有一些特定的性质。组的特性包括了组内单个套接口之间的相关特性和整个组的服务规范的特性。 
需要在网络上传输多媒体数据的应用程序会因为在所使用的一组套接口上建立联系而得到好处。至少这可以告诉服务提供者正在传输的数据流的一些相关性质。例如,一个会议应用程序希望传送音频数据的套接口比传送视频数据的套接口有更高的优先级。此外,一些传输服务提供者(例如数字电话和ATM)可以利用服务规范的组特性来决定底层调用或者线路连接的性质。通过应用程序指明套接口组及其特性,服务提供者可以以最大效率应用这些套接口。 
WSASocket()函数和WSAAccept()函数可以用来在创建一个新的套接口的同时显式的创建或者加入套接口组。getsockopt()函数可以用来得到套接口所属套接口组的标志。

6.9 共享套接口
为了在进程间共享套接口,Windows Sockets 2引入了WSADuplicateSocket()函数。共享套接口是通过对底层的套接口创建附加的套接口描述字实现的。该函数的输入是本地的套接口描述字和目标进程的句柄。它返回一个仅在目标进程中有效的新的套接口描述字(目标进程有可能就是原始进程)。这一机制既可以在单线程Windows版本(例如Windows 3.1)中使用,也可以在占先的多线程Windows版本(例如Windows 95和Windows NT)中使用。要注意的是,套接口可以在一个进程的不同线程中共享而不需要使用WSADuplicateSocket()函数,因为一个套接口描述字在进程的所有线程中都有效。
基于一个共享套接口的两个或者单个套接口描述字应该独立地使用套接口I/O。然而Windows Sockets没有实现任何共享控制。因此,在一个共享套接口上协调它们的操作是应用程序的责任。一个典型的使用共享套接口的例子是,有一个进程专门负责创建套接口和建立连接,并把套接口交给其他负责信息交换的进程。由于重新创建的是套接口描述字而不是底层的套接口,所以一切与套接口相关的状态对于所有套接口描述字都是相同的。例如对一个套接口描述字应用setsockopt()操作后,对所有的套接口描述字应用getsockopt()操作都可以看到这一变化。一个进程有可能调用closesocket()函数关闭一个复制的套接口描述字,于是该描述字就被清除了,然而,底层的套接口并不会被关闭,底层的套接口将一直保持打开,直到最后的一个套接口描述字被关闭。
选择对共享套接口的通知可以使用WSAAsyncSelect()函数和WSAEventSelect()函数。对任何共享的套接口描述字发出这些调用将会取消在这一套接口上的所有注册事件,无论先前的注册使用了那个套接口描述字。因此,如果应用程序想使进程A接收FD_READ事件,进程B接收FD_WRITE事件,这是做不到的。如果应用程序确实需要使用这种紧密的协调方式,我们建议应用程序开发者使用线程而不要使用进程。

6.10 连接建立和拆除的高级函数
WSAAccept()函数允许应用程序在接受连接请求以前得到请求者的信息,例如请求者的ID,QOS等等。这一点是通过对一个应用程序提供的条件函数的回调来实现的。如果服务提供者支持的话,在WSAConnect()函数的参数或者WSAAccept()函数的条件函数说明的用户对用户的数据可以在连接建立的时候传送到对方。
在连接拆除时,如果协议支持的话,也可以在通讯的端点间交换用户数据。需要提出拆除连接的通讯端点可以调用WSASendDisconnect()函数声明没有要传送的数据并启动连接拆除过程。对于某些协议,这一拆除过程包括了从发起拆除连接的一方发送拆除数据。在接收到远端已经启动了连接拆除过程的通知后(通常是FD_CLOSE),应用程序可以调用WSARecvDisconnect()函数接收某些拆除数据。
为了解释如何使用拆除数据,我们考虑如下的场景:在客户机/服务器模型中,通常是由客户机决定何时终止套接口的连接。在终止连接的同时,它通过拆除数据提供和服务器连接的次数。服务器也提供它和所有客户机的总的连接次数。这一过程如下所示: 

客户机端 服务器端
(1) 调用WSASendDisconnect()函数
终止对话并提供总的交互次数。
(2) 得到FD_CLOSE,recv()函数
返回0,或者WSARecv()函数返回
WSAEDISCON错误表示优雅的关闭。
(3) 调用WSARecvDisconnect()
函数来得到客户机的总的交互次
数。
(4) 计算累积授权次数。
(5) 调用WSASendDisconnect()
函数来传送累积授权次数。
(6) 接收FD_CLOSE指示 (5') 调用closesocket()函数。
(7) 调用WSARecvDisconnect() 
函数来接收并存放累积授权次数。
(8) 调用closesocket()函数。

注意:步骤(5')必须在步骤(5)之后执行,但是与步骤(6),(7)或(8)没有时间联系.

6.11 扩展的字节顺序转换例程
Windows Sockets 2并不假设对于所有协议,网络字节顺序都是正确的。所以Windows Sockets 2提供了一套把16位或者32位数字转换到网络字节顺序或者从网络字节顺序转换的例程。这些例程通常有一个整型的输入参数,它通常是一个常量,指明了需要的网络字节顺序是什么(目前或者是big_endian,或者是little_endian)。同时,每个协议的PROTOCOL_INFO结构包含一个域指明了协议对应的网络字节顺序,它可以用来作为字节顺序转换例程的输入参数。

6.12 分散/聚集方式I/O
WSASend(),WSASendTo(),WSARecv()和WSARecvFrom()函数都以应用程序缓冲区数组作为输入参数,因此它们可以进行分散/聚集方式(向量方式)的I/O操作。如果应用程序需要传送的信息除了信息体外还包含了一个或多个固定长度的头时,这种操作是很有用的。这些头在发送之前不需要由应用程序连接到一个连续的缓冲区中。同样的,在接收时,这些头会自动的分离到各自的缓冲区中。
如果接收时应用程序提供了多个缓冲区,当有数据到来时,操作就结束了,不论提供的缓冲区是否都被使用了。

6.13 协议无关的多点通讯
Windows Sockets 2支持基本的数据传输以一般的方式使用不同的传输协议。Windows Sockets 2也支持应用程序以一般的方式使用传输协议的多点通讯能力。
目前的多点通讯实现在节点加入一个多点对话的方式上有很大的不同。例如,是否有一个特殊的节点被指定为中心节点或者就是根节点;数据是在所有节点之间交换还是只在根节点和它的叶节点之间交换。Windows Sockets 2中的PROTOCOL_INFO结构允许一个协议声明它的多点通讯的各种特性。通过检查这些特性,应用程序可以知道在使用Windows Sockets 2函数设置,使用和拆除多点对话时应该遵循那一种协定。
Windows Sockets 2中为支持多点通讯而作的增加如下:
* PROTOCOL_INFO结构中的两个特性位。
* 为WSASocket()的参数iflags定义的四个标志。
* 一个新函数-WSAJoinLeaf(),它用来在多点对话中加入一个叶节点。
* 两个WSAIoctl()的命令代码。

6.14 新增套接口选项一览
Windows Sockets 2新增的套接口选项归纳如下:

选项值 类型 含义 缺省值

SO_GROUP_ID GROUP 套接口所属的套接口组 NULL 

SO_GROUP_PRIORITY int 套接口在套接口组中的 0
相对优先级

SO_MAX_MSG_SIZE int 对于基于消息的套接口, 决定于
这一选项指明了一个消 实现
息的最大长度。对于基
于流的套接口,这一选
项没有任何意义。

SO_PROTOCOL_INFO struct 描述捆绑到套接口的协 决定于
PROTOCOL 议的信息。 协议
_INFO 

PVD_CONFIG char 一个包含了服务提供者 决定于
FAR * 配置信息的不透明的数 实现
据结构对象。

6.15 新增套接口ioctl操作代码
Windows Sockets 2新增的ioctl操作代码归纳如下。WSAIoctol()函数支持所有为ioctlsocket()函数定义的操作代码。

操作代码 输入类型 输出类型 含义

SIO_ASSOCIATE_HANDLE 决定于伴随 没有使用。 把套接口与一个指定
的API。 的伴随接口连接。

SIO_ENABLE_CIRCULAR_ 没有使用 没有使用 允许循环队列。
QUEUEING

SIO_FIND_ROUTE struct 没有使用 请求找到对应于指定
sockaddr 地址的例程。

SIO_FLUSH 没有使用 没有使用 废除当前发送队列的内容。

SIO_GET_BROADCAST_ 没有使用 没有使用 得到特定协议的广播地址,
该地址可以使用在send()
函数和WSASend()函数中。

SIO_GET_QOS 没有使用 QOS 得到套接口当前的流协议。

SIO_GET_GROUP_QOS 没有使用 QOS 得到套接口所属套接口组的
流协议。

SIO_MULTIPOINT_LOOK BOOL 没有使用 决定多点对话的数据是否由
本地主机的同一套接口接收。

SIO_MULTICAST_SCOPE int 没有使用 定义允许多方传送的空间。

SIO_SET_QOS QOS 没有使用 为套接口建立新的流协议。

SIO_SET_GROUP_QOS QOS 没有使用 为套接口所属套接口组建立
新的流协议。

SIO_TRANSLATE_HANDLE int 决定于伴 得到一个上下文有效的套接口
随API 对应的句柄。

6.16 新增函数一览
Windows Sockets 2新增的函数列在下表中:

WSAAccept() accept()函数的扩展版本,它支持条件接收和套接口分组。
WSACloseEvent() 释放一个事件对象。
WSAConnect() connect()函数的扩展版本,它支持连接数据交换和QOS规范。
WSACreateEvent() 创建一个事件对象。
WSADuplicateSocket() 为一个共享套接口创建一个新的套接口描述字。
WSAEnumNetworkEvents() 检查是否有网络事件发生。
WSAEnumProtocols() 得到每个可以使用的协议的信息。
WSAEventSelect() 把网络事件和一个事件对象连接。 
WSAGetOverlappedResu() 得到重叠操作的完成状态。
WSAGetQOSByName() 对于一个传输协议服务名字提供相应的QOS参数。
WSAHtonl() htonl()函数的扩展版本。
WSAHtons() htons()函数的扩展版本。
WSAIoctl() ioctlsocket()函数的允许重叠操作的版本。
WSAJoinLeaf() 在多点对话中加入一个叶节点。
WSANtohl() ntohl()函数的扩展版本。
WSANtohs() ntohs()函数的扩展版本。
WSARecv() recv()函数的扩展版本。它支持分散/聚集I/O和重叠套接口操作。
WSARecvDisconnect() 终止套接口的接收操作。如果套接口是基于连接的,得到拆除数据。
WSARecvFrom() recvfrom()函数的扩展版本。它支持分散/聚集I/O和重叠套接口操作。
WSAResetEvent() 重新初始化一个数据对象。
WSASend() send()函数的或者版本。它支持分散/聚集I/O和重叠套接口操作。
WSASendDisconnect() 启动一系列拆除套接口连接的操作,并且可以选择发送拆除数据。
WSASendTo() sendto()函数的扩展版本。它支持分散/聚集I/O和重叠套接口操作。
WSASetEvent() 设置一个数据对象。
WSASocket() socket()函数的扩展版本。它以一个PROTOCOL_INFO结构作为输入参数,并且允许创建重叠套接口。它还允许创建套接口组。
WSAWaitForMultipleEvents() 阻塞多个事件对象。


地主 发表时间: 04/29 08:46

论坛: 编程破解

20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon

粤ICP备05087286号