offset 否则 其中 tran internal 如果 要求 定义 ber
1 重叠模型的优点1 可以运行在支持 Winsock2 的所有 Windows 平台, 而不像完成端口只支持 NT 系统
2 比起阻塞, select,WSAAsyncSelect 以及 WSAEventSelect 等模型, 重叠 I/O(Overlapped I/O) 模型使应用程序能达到更加系统性能
因为他和其他 4 种模型不同的是, 使用重叠模型的应用程序通知缓冲区收发系统直接使用数据, 也就是说, 如果应用程序
投递了一个 10kb 大小的缓冲区来接收数据, 而数据已经到达套接字, 则将该数据直接拷贝到投递的缓冲区,
而 4 种模型中, 数据达到并拷贝到单套接字接收缓冲区, 此时应用程序会被告知可以读入的容量, 当应用程序调用
接收函数之后, 数据才从单套接字缓冲区拷贝应用程序到缓冲区, 差别就体现了。
2 重叠模型的基本原理
重叠模型是让应用程序使用重叠数据结构 (WSAOVERLAPPED), 一次投递一个或多个 Winsock I/O 请求, 针对这些提交的
请求, 在他们完成之后, 应用程序会收到通知, 于是就可通过自己的代码来处理这些数据了。
使用事件通知的方法来实现重叠 IO 模型,基于事件的话, 就要求将 Win 事件与 WSAOVERLAPPED 结构关联在一起,
使用重叠结构, 常用的 send,sendto,recv,recvform 也被 WSASend,WSARecv 等替换掉,
OVERLAPPER SOCKET(重叠 Socket) 上进行重叠发送的操作,(简单的理解就是异步 send,recv)
他们的参数中都有一个 Overlapped 参数, 就是说所有的重叠 Socket 都要绑定到这个重叠结构体上,
提交一个请求, 其他的事情就交给重叠结构去操心, 而其中重叠结构要与 Windows 事件绑定在一起,
在样, 我们调用完 WSARecv 后. 等重叠操作完成, 就会有对应的事件来同意我们操作完成,
2 重叠模型的基础知识
- typedefstruct _OVERLAPPED {
- ULONG_PTR Internal;
- ULONG_PTR InternalHigh;
- union{
- struct{
- DWORD Offset;
- DWORD OffsetHigh;
- } DUMMYSTRUCTNAME;
- PVOID Pointer;
- } DUMMYUNIONNAME;
- HANDLE hEvent; //我们只要关注这个参数, 用来关联事件的
- } OVERLAPPED,*LPOVERLAPPED;
2WSARecv 系列函数
在重叠模型中, 接收数据就要靠他了, 他的参数也比 recv 多定义是这样的:
- intWSArecv( SOCKET s, //投递这个操作的套接字
- LPWSABUF lpBuffer, //接收缓冲区,与Recv函数不同
- LPDWORD lpNumberOfBytesRecvd, //如果接收操作立即完成,这里会返回函数调用
- LPDWORD lpFlags, //默认为0
- LPWSAOVERLAPPER lpOverlapper, //绑定的重叠结构
- LPWSAOVERLAPPER_COMPLETION_ROUTINE lpCompletionRoutine //一个回调
- ); 返回值: WSA_IO_PENDING:常见返回值,
- 说明WSARecv操作成功,
- 但是I / O材质没完成,
- 所以需要绑定一个事件来通知
3WSAWaitForMultipleEvents 函数
等待某个事件触发的函数, 我们需要事件通知我们完成重叠操作, 所以需要用到这个参数。
这个函数只能有 WSA_MAXIMUM_WAIT_EVENTS 对象定义的一个最大值, 是 64, 就是他只能等待 64 个事件
如果决的小了, 就要创建额外的线程, 或线程池。
- DWORD WSAWaitForMultipleEvents(
- DWORD cEvents, // 等候事件的总数量
- const WSAEVENT* lphEvents, // 事件数组的指针
- BOOL fWaitAll, // 如果设置为TRUE则事件中所有的事件被传信才返回,FALSE是当有事件立即返回
- DWORD dwTimeout, // 超时时间,如果超时,函数会返回 WSA_WAIT_TIMEOUT
- // 如果设置为0,函数会立即返回 // 如果设置为 WSA_INFINITE只有在某一个事件被传信后才会返回
- BOOL fAlertable ) // 默认用FALSE
- 返回值:
- WSA_WAIT_TIMEOUT :最常见的返回值,我们需要做的就是继续等待
- WSA_WAIT_FAILED :出现了错误,请检查cEvents和lphEvents两个参数是否有效
4WSAGetOverlappedResult 函数
既然通过 WSAWaitForMultipleEvents 函数来得到重叠操作的结果, 那我们也需要一个函数来查询
一下重叠操作的结果, 这个函数不需要关注返回值
- BOOL WSAGetOverlappedResult(
- SOCKET s, // SOCKET,不用说了
- LPWSAOVERLAPPED lpOverlapped, // 这里是我们想要查询结果的那个重叠结构的指针
- LPDWORD lpcbTransfer, // 本次重叠操作的实际接收(或发送)的字节数
- BOOL fWait, // 设置为TRUE,除非重叠操作完成,否则函数不会返回
- // 设置FALSE,而且操作仍处于挂起状态,那么函数就会返回FALSE
- LPDWORD lpdwFlags // 指向DWORD的指针,负责接收结果标志
- 第二个参数是输出的 第三个参数也是输出的,就是你接收的字节数为0那说明对方关闭socket了
来源: http://www.bubuko.com/infodetail-2452256.html