重叠I/O(Overlapped I/O)
在 Winsock 中,重叠 I/O(Overlapped I/O)模型能到达更佳的系统性能,高于之前讲过的三种。重叠模型的根基设计道理等于让应用措施使用一个重叠的数据布局(WSAOVERLAPPED),一次投递一个或多个 Winsock I/O 请求。针对这些提交的请求,在它们完成之后,我们的应用措施会收到通知,于是我们就可以对数据进行措置惩罚惩罚了。
套接字的重叠I/O模型才是真正意义上的异步I/O模型。在应用措施中挪用输入或输出函数后,当即返回。当I/O操纵完成后,系统通知应用措施。操作该模型,应用措施在挪用输入或者输出函数后,只需要期待I/O操纵完成的通知即可。 从发送和接收数据操纵的角度看,前3个模型不是异步模型。因为在这3个模型中,I/O操纵还是同步的。 重叠I/O模型才是真正意义上的异步模型。
四种模型对照:
前三个模型主要区别在第一阶段。Select模型操作select函数主动查抄系统中套接字是否满足可读条件。而WSAAsyncSelect模型和WSAEventSelect模型则被动期待系统通知。当系统产生FD_READ网络事件时,WSAAsyncSelect模型以动静的形式接收通知,WSAEventSelect模型以事件形式接收通知。
在第二个阶段,前三个模型基真不异。在将数据从系统复制到用户缓冲区时,线程梗阻于函数的挪用。重叠I/O模型与前3个模型差别。Windows Sockets 应用措施在挪用输入函数后,只需期待接收完成系统I/O操纵后发送通知。
实现要领:
要想在一个套接字上使用重叠 I/O 模型,首先必需使用 WSA_FLAG_OVERLAPPED 这个标识表记标帜,创建一个套接字。例如: SOCKET s = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
创建套接字的时候,假如使用的是 socket 函数,那么会默认设置 WSA_FLAG_OVERLAPPED 标识表记标帜。
告成建好一个套接字,同时将其与一个本地接口绑定到一起后,便可开始进行重叠 I/O 操纵,为了要使用重叠布局,我们常用的 send、recv 等收发数据的函数也都要被 WSASend、WSARecv 替换失了,要领是挪用下述的 Winsock 函数,同时指定一个 WSAOVERLAPPED 布局(可选),它们的用法我后面会讲到: ■ WSASend ■ WSASendTo ■ WSARecv ■ WSARecvFrom ■ WSAIoctl ■ AcceptEx
WSA_IO_PENDING : 最常见的返回值,这是说明我们的重叠函数挪用告成了,但是 I/O 操纵还没有完成。
若随一个 WSAOVERLAPPED 布局一起挪用这些函数,函数会当即完成并返回,无论套接字是否设为梗阻模式。 那么我们如何来得知我们的 I/O 请求是否告成了呢?要领有两个: ■ 期待“事件东西通知”; ■ 通过“完老例程”。
I/O模型实现——事件通知
重叠函数(如:WSARecv)的参数中都有一个 Overlapped 参数,我们可以假设是把我们的WSARecv这样的操纵“绑定”到这个重叠布局上,提交一个请求,而不是将操纵当即完成,其他的工作就交给重叠布局去做,而此中重叠布局又要与Windows的事件东西“绑定”在一起,这样我们挪用完 WSARecv 以后就可以“不劳而获”,等到重叠操纵完成以后,自然会有与之对应的事件来通知我们操纵完成,然后我们就可以来按照重叠操纵的功效取得我们想要的数据了。
WSAOVERLAPPED 布局
重叠 I/O 的事件通知要领要求将 Win32事件东西与 WSAOVERLAPPED 布局关联在一起,当 I/O 操纵完成后,事件的状态会酿成“有信号”状态,即激发态(是不是跟上节课给大家讲的事件选择模型很像?);
下面来看一下 WSAOVERLAPPED 布局的界说: typedef struct _WSAOVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
WSAEVENT hEvent;
} WSAOVERLAPPED, FAR * LPWSAOVERLAPPED;
此中,Internal、InternalHigh、Offset 和 OffsetHigh 字段均由系统在内部使用,不应由应用措施直接进行措置惩罚惩罚或使用。而另一方面,hEvent 字段有点儿特殊,它允许应用措施将一个事件东西句柄同一个套接字关联起来 。