重叠的 I/O 和事件对象

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

注意

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

 

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

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

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

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

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

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

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

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