第六章 WINDOWS SOCKET 2的扩展特性.docx

上传人:b****5 文档编号:6650717 上传时间:2023-01-08 格式:DOCX 页数:14 大小:83.49KB
下载 相关 举报
第六章 WINDOWS SOCKET 2的扩展特性.docx_第1页
第1页 / 共14页
第六章 WINDOWS SOCKET 2的扩展特性.docx_第2页
第2页 / 共14页
第六章 WINDOWS SOCKET 2的扩展特性.docx_第3页
第3页 / 共14页
第六章 WINDOWS SOCKET 2的扩展特性.docx_第4页
第4页 / 共14页
第六章 WINDOWS SOCKET 2的扩展特性.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

第六章 WINDOWS SOCKET 2的扩展特性.docx

《第六章 WINDOWS SOCKET 2的扩展特性.docx》由会员分享,可在线阅读,更多相关《第六章 WINDOWS SOCKET 2的扩展特性.docx(14页珍藏版)》请在冰豆网上搜索。

第六章 WINDOWS SOCKET 2的扩展特性.docx

第六章WINDOWSSOCKET2的扩展特性

第六章WindowsSocket2的扩展特性

这一章将讨论从WindowsSockets1.1到WindowsSocket2的主要变动。

6.1同时使用多个传输协议

为了用户能够同时使用多个传输协议,在WindowsSocket2中,结构有所改变。

在WindowsSockets1.1中,软件开发商所提供的DLL实现了WindowsSockets的API和TCP/IP协议栈。

WindowsSocketsDLL和底层协议栈的接口是唯一而且独占的。

WindowsSocket2改变了这种模型:

它定义了一个WindowsSocketsDLL和底层协议栈间的标准服务提供接口(SPI)。

这使得一个WindowsSocketsDLL能够同时访问不同软件开发商的多个底层协议栈。

此外,WindowsSockets2并不象WindowsSockets1.1仅支持TCP/IP协议栈。

与Windows开放系统结构(WOSA)兼容的WindowsSockets2的结构如下图:

图6-1:

WindowsSocket2开放系统结构图

注意:

16位的WindowsSockets2应用程序应使用WS2-16.DLL,而32位的WindowsSockets2应用程序应使用WS2-32.DLL。

但今后,为了简单起见,它们将都使用WINSOCK.DLL。

这并不会造成任何问题,因为在它们之间并没有任何语法上的区别。

由于以上的结构,现在已没有必要每个协议栈开发商都提供它们自己的WINSOCK.DLL(甚至这样做也不是期望的)。

因为任何一个WINSOCK.DLL能够在所有协议栈上工作。

因此,WINSOCK.DLL可以被看作是一个操作系统组件。

Microsoft将在Windows95和WindowsNT上提供一个32位的WINSOCK.DLL。

Intel公司目前正在打算提供Windows3.1和Windows3.11上的WindowsSockets2兼容的16位WINSOCK.DLL。

6.2与WindowsSocket1.1应用程序的向后兼容性

WindowsSocket2与WindowsSockets1.1在两个基础上向后兼容:

源码和二进制代码。

这就实现了WindowsSockets应用程序和任何版本的WindowsSockets实现之间的最大的互操作性,而且也减少了WindowsSockets应用程序使用者,网络协议栈提供者和服务提供者的许多痛苦。

现有的WindowsSockets1.1兼容的应用程序可以在WindowsSockets2实现上不加修改的运行,只要有一个TCP/IP协议栈被安装。

6.2.1源码的兼容性

WindowsSockets2中的源码兼容性意味着所有的WindowsSockets1.1版的API在WindowsSockets2中都被保留了下来。

这意味着现有的WindowsSockets1.1应用程序的原程序可以被简单的移植到WindowsSockets2系统上运行。

程序员需要做的只是包含新的头文件-WINSOCK2.H和简单的与合适的WindowsSockets2函数库的连接。

应用程序开发者应该把这种工作看作是完全转向WindowsSockets2的第一步,因为有许多方式可以使用WindowsSockets2中的新函数来提高原来的WindowsSockets1.1应用程序的运行性能。

6.2.2二进制兼容性

在设计WindowsSockets2时的一个主要目标就是使得现有的WindowsSockets1.1应用程序在二进制级别上能够不加修改的应用于WindowsSockets2之上。

由于WindowsSockets1.1是基于TCP/IP上的,二进制兼容性就要求WindowsSockets2系统提供基于TCP/IP上的WindowsSockets2的传输和名字解析服务。

为了WindowsSockets1.1应用程序能在这种意义上运行,WindowsSockets2系统提供了一个附加的组件-WindowsSockets1.1的DLL。

WindowsSockets2安装时的提示保证了在终端机用户引进WindowsSockets2系统时不会对已有的WindowsSockets软件环境有任何影响。

图6-2:

与WindowsSockets1.1二进制兼容性结构图

一个完全的WindowsSockets1.1二进制兼容的必要的前提是在系统上已经安装了至少一个TCP/IP协议栈并且在WindowsSockets2中做了注册。

WindowsSockets1.1目前通过WSAData结构中的某些元素来得到关于底层TCP/IP协议栈的信息(例如通过WSAStartup()函数调用),这些信息包括iMaxSockets,iMaxUdpDg和IPVendorInfo。

但是在WindowsSockets2中,应用程序应该知道忽略这些信息,因为这些值不能统一地适用于所有协议栈。

不过DLL必须仍然提供这些值以免破坏WindowsSockets1.1的应用程序。

这些信息只能从(因此也只能应用于)缺省的TCP/IP服务提供者得到。

缺省的TCP/IP服务提供者是由WSAEnumProtocols()调用返回的PROTOCOL_INFO结构缓冲区的第一条TCP/IP协议栈。

6.3在WindowsSockets中注册传输协议

要使WindowsSockets能够利用一个传输协议,该传输协议必须在系统上安装并且在WindowsSockets中注册。

WindowsSockets2的DLL包含了一组API来完成这个注册过程。

这个注册过程包括建立一个新的注册和取消一个已有的注册。

在建立新的注册时,调用者(假设是协议栈开发商的安装程序)必须提供一组或多组完整的关于协议的信息,这些信息将被用来填充PROTOCOL_INFO结构。

6.3.1使用多个协议

一个应用程序可以通过WSAEnumProtocols()功能调用来得到目前有多少个传输协议可以使用,并且得到与每个传输协议相关的信息,这些信息包含在PROTOCOL_INFO结构中。

然而,某些传输协议可能表现出多种行为。

例如SPX是基于消息的(发送者发送的消息的边界在网络上被保留了),但是接收的一方可以选择忽略这些边界并把套接口作为一个字节流来对待。

这样就很合理地导致了SPX有两个不同的PROTOCOL_INFO结构条目,每一个条目对应了一种行为。

在WindowsSockets1中仅有一个地址族(AF_INET),它包含了数量不多的一些众所周知的套接口类型和协议标识符。

这在WindowsSockets2中已经有所改变。

除了现有的地址族,套接口类型和协议标识符为了兼容性原因被保留以外,WindowsSockets2加入了许多唯一的但是可能并不为大家所知的地址族,套接口类型和协议标识符。

不为大家所知并不意味着会对应用程序开发造成问题,因为一个企图做成协议无关的应用程序应该在对自身合适的基础上选择协议而不应该依赖于某个分配给它的特定的套接口类型或协议类型值。

PROTOCOL_INFO结构中包含的通讯性质指明了协议的合适性(例如:

基于消息的对应于基于字节流的,可靠的对应于不可靠的,等等)。

基于合适性原则选取协议而不使用某个特定的协议名和套接口类型。

对于客户机/服务器模型,服务器一端的应用程序最好能够在所有合适的传输协议上建立监听套接口。

这样,客户机一端的应用程序就可以通过任何合适的传输协议来与服务器一端的应用程序建立连接。

这样做可以使得一个客户机应用程序易于移植。

例如一台运行于LAN上的台式机的客户机应用程序在转到运行于无线网上的笔记本计算机时就不用作任何改变。

6.3.2select()函数应用中关于多个服务提供者的限制

在WindowsSockets2中,函数select()使用FD_SET仅能应用于和单个服务提供者相连的套接口。

但是这并不限制一个应用程序使用多个服务提供者打开多个套接口。

如果应用程序开发者喜欢使用非阻塞方式编程,那么可以使用WSAAsyncSelect()函数。

由于该函数需要一个套接口描述字作为输入参数,那么与该套接口相连的服务提供者是很重要的。

如果一个应用程序需要在一组跨越多个服务提供者的套接口上使用带有阻塞语法的函数,那么应该使用WSAWaitForMultipleEvents()函数。

应用程序也可以使用WSAEventSelect()函数。

该函数允许应用程序把FD_XXX网络事件和一个事件对象相连接,并且在该事件对象中处理网络事件(这一模式将在下文讨论)。

6.4协议无关的名字解析

WindowsSockets2包含了应用程序可以使用的多种标准化的网络名字服务。

WindowsSockets2应用程序并不需要理解与名字服务相关的许多迥异的接口(例如DNS,NIS,X.5000,SAP等等)。

本书的4.2介绍了这一主题,并对API做了详细介绍。

6.5重叠I/O和事件对象

WindowsSockets2引入了重叠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概念的引入需要建立一个机制使得应用程序能够正确的把发送和接收事件与今后它们完成时的指示相连接。

在WindowsSockets2中,这一点是通过事件对象实现的,它采用了Win32事件的模型。

WindowsSockets事件对象是一个相当简单的结构,它可以被创建,关闭,设置,清除,等待和检查。

它们的主要用处是使得应用程序能够阻塞并等待直到一个或多个事件对象被设置。

应用程序可以使用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接收操作完成指示

为了提供给应用程序适当的灵活性,WindowsSockets2为接收操作完成指示提供了多个选项。

它们包括:

等待(阻塞)事件对象,检查事件对象和套接口I/O完成例程。

6.5.2.1阻塞并且等待完成指示。

应用程序可以使用WSAWaitForMultipleEvents()函数来选择阻塞程序直到一个或多个事件对象被设置。

在Win16实现中,这种方式将使用一个阻塞钩子,就象在标准的阻塞套接口操作时一样。

在Win32实现中,进程或线程会被真正地阻塞。

因为WindowsSockets2事件对象被实现成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文挡说明的在一个多媒体定时回调函数中可以被安全调用的运行时函数库。

在Windows95和WindowsNT中,完成例程与Win32文件I/O完成例程遵循着同样的规则。

在所有的环境中,传输协议允许应用程序以完成例程的方式唤起发送和接收操作,而且保证对于给定的一个套接口,I/O完成例程不会嵌套。

这就允许了在一个占先的环境中进行对时间敏感的数据的传送。

6.5.3WSAOVERLAPPED的细节

WSAOVERLAPPED结构提供了一个重叠I/O操作的初始化和它将来的如何被完成之间的通讯媒体。

WSAOVERLAPPED结构被设计成与Win32中的OVERLAPPED结构兼容:

typedefstructWSAOVERLAPPED{

DWORDInternal;//reserved

DWORDInternalHigh;//reserved

DWORDOffset;//ignored

DWORDOffsetHigh;//ignored

WSAEVENThEvent;

}WSAOVERLAPPED,LPWSAOVERLAPPED;

Internal这一个保留的域是由重叠I/O实现的实体内部使用的。

对于使用类文件方式创建套接口的传输服务提供者,这一域是被底层的操作系统使用的;对于其他的传输服务提供者(那些创建伪句柄的),可以视需要使用这个域。

InternalHigh这一个保留的域是由重叠I/O实现的实体内部使用的。

对于使用类文件方式创建套接口的传输服务提供者,这一域是被底层的操作系统使用的;对于其他的传输服务提供者(那些创建伪句柄的),可以视需要使用这个域。

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

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

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

6.6使用事件对象异步通知

为了适应一些应用程序例如精灵程序或者某些没有用户界面的服务程序(因此不使用窗口句柄),WindowsSocket2提供了WSAEventSelect()函数和WSAEnumNetworkEvents()函数。

WSAEventSelect()函数和WSAAyncSelect()函数很类似,区别仅在于当一个FD_XXX网络事件发生时,WSAEventSelect()函数将导致一个应用程序指定的事件对象被设置,而WSAAyncSelect()将导致一条Windows消息被发送(例如FD_READ,FD_WRITE等等)。

此外,传输服务提供者会记住每个特定的FD_XXX网络事件的发生。

应用程序可以调用WSAEnumNetworkEvents()函数把目前的网络事件记忆拷贝到应用程序提供的缓冲区中,并且自动清除网络事件记忆。

如果需要,应用程序还可以把某个特定的事件对象和网络事件记忆一起清除。

6.7服务的质量(QOS)

WindowsSockets2中的QOS机制是从CraigPartridge在RFC1363中描述的流规格引入的。

这一概念可以大致描述如下:

流规格描述了一个网络上单向数据流的性质的集合。

应用程序可以在调用WSAConnect()函数发出连接请求或者使用WSAIoctl()函数等其他QOS命令时,把一对流规格和一个套接口连接(一个规范对应了一个方向)。

流规格以参数方式声明了应用程序所要求的服务的级别,并且为应用程序适应不同的网络条件提供了一套反馈机制-如果应用程序要求的服务级别不能达到,应用程序是否愿意松动它的要求。

WindowsSockets2中QOS的使用模型如下:

对于基于连接的传输服务,应用程序可以很方便的在使用WSAConnect()函数提出连接请求时规定它所要求的服务质量(QOS)。

要注意的是:

如果应用程序在调用WSAConnect()时QOS参数不为空,那么对于基于连接的套接口,任何预先设置的QOS都会被覆盖。

如果WSAConnect()函数成功返回,应用程序就会知道它所要求的QOS已经被网络接受,那么应用程序就可以随意的使用这个套接口进行数据交换。

如果连接操作由于资源有限而失败,应用程序应该适当地降低它所要求的服务质量或者干脆就放弃操作。

在每次连接企图之后(不论成功与否),传输服务提供者都会更新flow_spec结构,以便尽可能地指明目前的网络条件。

如果应用程序所要求的服务质量仅仅包含了一些传输服务提供者必须满足的缺省值,那么这种更新会是很有用处的。

应用程序可以利用这些关于当前网络条件的信息来指导自己使用网络,例如今后的QOS要求。

然而应用程序应该注意的是,传输服务提供者在不断更新的flow_spec结构中提供的信息仅仅是一个参考,它们只不过是粗略的估计。

应用程序应该很小心的解释这些数据。

无连接的套接口也可以使用WSAConnect()函数为一个指定的通讯规定特定的QOS级别。

WSAIoctl()函数也可以用来规定初始的QOS要求,或者用来今后的QOS协商。

即使是一个流规格已经建立,网络的情况也有可能改变,或者通讯的一方可能提出了QOS重协商的要求,这将导致可以得到的服务级别的降低或者提高。

WindowsSockets2引入了一个通知机制。

它使用了一般的WS通知方式(FD_QOS和FD_GROUP_QOS事件)来告诉应用程序QOS级别已经改变了。

一般服务提供者只在当前的服务级别和上一次报告有很大区别(通常是逆向的),并且有可能会影响到应用程序时才发出FD_QOS/FD_GROUP_QOS通知。

应用程序应该使用WSAIoctl()函数来得到当前的状态并且检查服务等级的那些方面有了变化。

如果当前的QOS级别是不可接受的,应用程序应该调整自己以去适应当前的状态,试图重新协商或者关闭套接口。

WindowsSockets2推荐的流规格把QOS特性划分为如下几个方面:

1.源通讯描述:

应用程序的通讯事件以什么方式被送入网络。

2.延时性:

最大延时和可接受的延时变化。

3.需要保证的服务级别:

应用程序是否要求对服务质量的绝对保证。

4.费用:

这一项是为将来可以决定有意义的费用时保留的。

5.服务提供者特定的参数:

流规格可以根据具体的提供者扩展。

6.8套接口组

WindowsSockets2引入了一个所谓套接口组的概念。

它允许应用程序(或者一组共同工作的应用程序)通知底层的服务提供者一组特定的套接口是相关的,它们享有一些特定的性质。

组的特性包括了组内单个套接口之间的相关特性和整个组的服务规范的特性。

需要在网络上传输多媒体数据的应用程序会因为在所使用的一组套接口上建立联系而得到好处。

至少这可以告诉服务提供者正在传输的数据流的一些相关性质。

例如,一个会议应用程序希望传送音频数据的套接口比传送视频数据的套接口有更高的优先级。

此外,一些传输服务提供者(例如数字电话和ATM)可以利用服务规范的组特性来决定底层调用或者线路连接的性质。

通过应用程序指明套接口组及其特性,服务提供者可以以最大效率应用这些套接口。

WSASocket()函数和WSAAccept()函数可以用来在创建一个新的套接口的同时显式的创建或者加入套接口组。

getsockopt()函数可以用来得到套接口所属套接口组的标志。

6.9共享套接口

为了在进程间共享套接口,WindowsSockets2引入了WSADuplicateSocket()函数。

共享套接口是通过对底层的套接口创建附加的套接口描述字实现的。

该函数的输入是本地的套接口描述字和目标进程的句柄。

它返回一个仅在目标进程中有效的新的套接口描述字(目标进程有可能就是原始进程)。

这一机制既可以在单线程Windows版本(例如Windows3.1)中使用,也可以在占先的多线程Windows版本(例如Windows95和WindowsNT)中使用。

要注意的是,套接口可以在一个进程的不同线程中共享而不需要使用WSADuplicateSocket()函数,因为一个套接口描述字在进程的所有线程中都有效。

基于

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1