关于Winsock:重叠的I / O和事件对象

Windows套接字2支持重叠I / O,所有传输提供程序都支持此功能。 重叠I / O遵循Windows中建立的模型,可以在使用套接字函数创建的套接字上执行,也可以使用WSASocket函数创建的套接字执行,并在dwFlags参数中设置WSA_FLAG_OVERLAPPED标志。

注意

使用重叠属性创建套接字对套接字当前是处于阻塞还是非阻塞模式没有影响。 使用重叠属性创建的套接字可用于执行重叠I / O操作,因此不会更改套接字的阻塞模式。 由于重叠的I / O操作不会阻塞,因此套接字的阻塞模式与这些操作无关。

对于接收,应用程序使用WSARecv或WSARecvFrom函数来提供要接收数据的缓冲区。 如果在网络接收到数据之前发布了一个或多个缓冲区,则该数据可以在到达时立即放入用户的缓冲区中。 因此,它可以避免在调用recv或recvfrom函数时发生的复制操作。 如果在发布接收缓冲区时数据已存在,则会立即将其复制到用户的缓冲区中。

如果数据在应用程序未发布接收缓冲区时到达,则网络将采用熟悉的同步操作方式。 也就是说,输入数据在内部缓冲,直到应用程序发出接收调用,从而提供可以复制数据的缓冲区。 例外情况是应用程序使用setsockopt将接收缓冲区的大小设置为零。 在这种情况下,可靠的协议只允许在发布应用程序缓冲区时接收数据,并且丢失不可靠协议上的数据。

在发送端,应用程序使用WSASend或WSASendTo提供指向已填充缓冲区的指针,然后同意在网络消耗缓冲区内容之前不以任何方式干扰缓冲区。

重叠的发送和接收呼叫立即返回。 返回值为零表示I / O操作立即完成,并且已经发生了相应的完成指示。 也就是说,已经发信号通知了相关的事件对象,或者已经对完成例程进行了排队,并且当调用线程进入可警告的等待状态时将执行该事件对象。

SOCKET_ERROR的返回值加上错误代码WSA_IO_PENDING表示已成功启动重叠操作,并且在消耗了发送缓冲区或接收操作已完成时将提供后续指示。 但是,对于字节流样式的套接字,无论缓冲区是否已满,每当传入数据耗尽时都会发生完成指示。 任何其他错误代码表示重叠操作未成功启动,并且没有完成指示即将到来。

发送和接收操作都可以重叠。 可以多次调用接收函数以发布接收缓冲区以准备传入数据,并且可以多次调用发送函数以对要发送的多个缓冲区进行排队。 虽然应用程序可以依赖于以所提供的顺序发送的一系列重叠的发送缓冲区,但是相应的完成指示可能以不同的顺序发生。 同样,在接收方,缓冲区可以按它们提供的顺序填充,但完成指示可能以不同的顺序发生。

在许多情况下,使用AcceptEx,ConnectEx,WSASend,WSARecv,TransmitFile和类似函数的Winsock重叠操作是可取消的。 但是,对于已取消未完成操作的套接字的继续使用,行为未定义。 取消重叠操作后应调用closesocket函数。 因此,为了获得最佳结果,不应直接取消I / O,而应调用closesocket函数来关闭套接字,最终将终止所有挂起的操作。

重叠I / O的延迟完成功能也可用于WSAIoctl,它是ioctlsocket的增强版本。

 

事件对象

引入重叠I / O需要一种机制,使应用程序能够明确地将发送和接收请求与其后续完成指示相关联。 在Windows套接字2中,这是通过在Windows事件之后建模的事件对象来完成的。 Windows套接字事件对象是相当简单的构造,可以创建和关闭,设置和清除,等待和轮询。 它们的主要功能是应用程序阻止并等待一个或多个事件对象设置的能力。

应用程序使用WSACreateEvent获取事件对象句柄,然后可以将其作为必需参数提供给发送和接收调用的重叠版本(WSASend,WSASendTo,WSARecv,WSARecvFrom)。 首次创建时清除的事件对象由传输提供程序在关联的重叠I / O操作完成(成功或有错误)时设置。 WSACreateEvent创建的每个事件对象都应该有一个匹配的WSACloseEvent来销毁它。

WSAEventSelect中还使用事件对象将一个或多个FD_XXX网络事件与事件对象相关联。 在使用事件对象的异步通知中对此进行了描述。

在32位环境中,与事件对象相关的函数(包括WSACreateEvent,WSACloseEvent,WSASetEvent,WSAResetEvent和WSAWaitForMultipleEvents)使用相同的函数名称直接映射到相应的本机Windows函数,但没有WSA前缀。

 

接收完成指示

有几种方法可用于接收完成指示,从而为应用程序提供适当的灵活性。 其中包括:等待(或阻塞)事件对象,轮询事件对象和套接字I / O完成例程。

 

阻止和等待完成指示

应用程序可以在等待使用WSAWaitForMultipleEvents函数设置一个或多个事件对象时阻塞。 在Windows实现中,进程或线程真正阻塞。 由于Windows Sockets 2事件对象是作为Windows事件实现的,因此本机Windows函数WaitForMultipleObjects也可用于此目的。 如果线程需要在套接字和非套接字事件上等待,这尤其有用。

 

轮询完成指示

不想阻止的应用程序可以使用WSAGetOverlappedResult函数来轮询与任何特定事件对象关联的完成状态。 此函数指示重叠操作是否已完成,如果已完成,则安排WSAGetLastError函数检索重叠操作的错误状态。

 

使用套接字I / O完成例程

用于启动重叠I / O的函数(WSASend,WSASendTo,WSARecv,WSARecvFrom)都将lpCompletionRoutine作为可选的输入参数。 这是指向成功启动的重叠I / O操作完成(成功或其他)后调用的特定于应用程序的函数的指针。 完成例程遵循与Windows文件I / O完成例程相同的规则。 也就是说,在线程处于可警告的等待状态之前不会调用完成例程,例如在设置了FALERTABLE标志的情况下调用函数WSAWaitForMultipleEvents时。 对特定重叠I / O请求使用完成例程选项的应用程序可能不会对同一重叠I / O请求使用WSAGetOverlappedResult的wait选项。

传输允许应用程序从套接字I / O完成例程的上下文中调用发送和接收操作,并保证对于给定的套接字,I / O完成例程将不会嵌套。 这允许时间敏感的数据传输完全在抢占上下文中发生。

 

重叠完井指示机制综述

用于给定重叠操作的特定重叠I / O完成指示由应用程序是否提供指向完成函数的指针,是否引用WSAOVERLAPPED结构以及WSOAVERLAPPED结构中的hEvent成员的值来确定( 如果提供)。 下表总结了重叠套接字的完成语义,并显示了lpOverlapped,hEvent和lpCompletionRoutine的各种组合:

lpOverlappedhEventlpCompletionRoutineCompletion indication
NULLNot applicableIgnored操作同步完成。 它表现得好像是一个非重叠的套接字。
!NULLNULLNULL操作完成重叠,但没有Windows Sockets 2支持的完成机制。 在这种情况下,可以使用完成端口机制(如果支持)。 否则,没有完成通知。
!NULL!NULLNULL操作完成重叠,通过信号事件对象进行通知。
!NULLIgnored!NULL操作完成重叠,通过调度完成例程进行通知。

 

使用事件对象的异步通知

提供WSAEventSelect和WSAEnumNetworkEvents函数以适应诸如守护程序和没有用户界面的服务之类的应用程序(因此不使用Windows句柄)。 WSAEventSelect函数的行为与WSAAsyncSelect函数完全相同。 但是,不是在发生FD_XXX网络事件(例如,FD_READ和FD_WRITE)时发送Windows消息,而是设置应用程序指定的事件对象。

此外,服务提供商还记住发生特定FD_XXX网络事件的事实。 应用程序可以调用WSAEnumNetworkEvents将网络事件存储器的当前内容复制到应用程序提供的缓冲区,并自动清除网络事件存储器。 如果需要,应用程序还可以指定与网络事件存储器一起清除的特定事件对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值