WinSock IO模型---重叠模型
来源:互联网 发布:linux 防火墙 firewall 编辑:程序博客网 时间:2024/04/19 09:34
重叠IO(overlapped IO)是可以是应用程序达到好的系统性能;
设计的原理便是:让应用程序使用一个重叠的数据结构,一次投递一个或者多个IO请求。
1.创建一个套接字,并在指定的端口上监听。
使用下面的函数,并设置WSA_FLAG_OVERLAPPED这个标志创建套接字,创建套接字时候假如使用的是socket则默认设置好了该标志。
s=WSASocket(AF_INET,SOCK_STREAM,0,WSA_FLAG_OVERLAPPED);
2.创建成功以后,将其与本地的接口绑定到一起,便可以进行重叠的IO操作。
3.接收一个进入的请求。
4.为接受的套接字新建一个WSAOVERLAPPED结构,并为该结构分配一个事件对象句柄,把该句柄分配一个事件数组,以便稍后在WSAWaitForMultipleEvents中使用。
结构体的说明:
typedef struct _WSAOVERLAPPED
{ ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union
{
struct
{
DWORD Offset;
DWORD OffsetHigh; //前4个参数有系统内部使用,程序不直接使用处理
};
PVOID Pointer;
};
HANDLE hEvent;//允许将一个套接字和和事件关联在一起;
} WSAOVERLAPPED, *LPWSAOVERLAPPED;
5.在套接字上投递一个异步的WSARecv请求,指定参数WSAOVERLAPPED结构。
注:函数通常会失败,返回SOCKET_ERROR状态WSA_IO_PENGING(io操作未完成);
6.使用4中的事件数组,调用WSAWaitForMultipleEvents等待与重叠关联事件变成传信状态。
说明:一个重叠请求操作最终完成之后,在事件的通知方法中,winsock会把WSAOVERLAPPED结构中的事件由未传信状态变为已传信状态;事件已经分配给了WSAOVERLAPPED所以只需要简单的调用WSAWaitForEvents就可以判断出一个IO调用在什么时候完成。
7.WSAWaitForMultipleEvent函数完成后,针对事件数组,调用WSAResetEvent重设事件对象,并对完成的重叠请求进行处理;
8.使用WSAGetOverlappedResult函数,判断重叠调用的返回状态是什么。
说明:发现一次重叠请求完成之后,需要调用WSAGetOverlappedResult(获得重叠结构)函数,来判断那个重叠请
求到底是成功,还是失败。
BOOL WSAGetOverlappedResult
(
IN SOCKET s, //重叠操作开始时,与之对应的套接字
IN LPWSAOVERLAPPED lpOverlapped, //WSAOVERLAPPED
OUT LPDWORD lpcbTransfer, //负责接收一次重叠发送或者接收实际传输的字节
IN BOOL fWait, //确定函数是否应该等待一次未完成的重叠操作完成;TRUE表示一直等到操作完成再返回;
OUT LPDWORD lpdwFlags //负责接收结果标志
)
返回值的分析:该函数成功返回的TRUE,表示我们的重叠IO已经完成。而且lpcbTransfer函数指向的值已经得到更新,如果返回的是FALSE则可能是一下的原因:1.重叠的IO仍然在待决的状态。
2.重叠IO完成,但是有错误。
3.重叠IO的完成状态不可以判断,因为传递给该函数的一个或者多个参数存在错误;
9.在套接字上投递里另外一个重叠WSARecv请求。
10.重复6--9;
示例代码:
#include "stdafx.h"#include <stdio.h>#include <WinSock2.h>#include <Windows.h>#pragma comment(lib,"ws2_32.lib")#define PORT 5150#define DATA_BUFFER 4096int _tmain(int argc, _TCHAR* argv[]){WSADATA WSAdata;SOCKET sListen,sAccept;WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];WSAOVERLAPPED overlapped;DWORD EventTotal=0;DWORD byteRecv=0;DWORD Flags=0;DWORD ByteTranfer=0;WSABUF wsabuf;char buffer[DATA_BUFFER];if ((WSAStartup(MAKEWORD(2,2),&WSAdata))!=0){printf("WSAStartup() Failed with error %d",WSAGetLastError());return 0;} sListen=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);if (sListen==INVALID_SOCKET){printf("socket() Failed with error %d",WSAGetLastError());return 0;} SOCKADDR_IN listenAddr;listenAddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);listenAddr.sin_family=AF_INET;listenAddr.sin_port=htons(PORT);if (bind(sListen, (PSOCKADDR)&listenAddr, sizeof(listenAddr)) == SOCKET_ERROR){printf("bind() failed with error %d\n", WSAGetLastError());return 0;}if (listen(sListen, 5)){printf("listen() failed with error %d\n", WSAGetLastError());return 0;}printf("Listening...\n"); sAccept=accept(sListen,NULL,NULL);if (sListen==INVALID_SOCKET){printf("accept() Failed with error %d",WSAGetLastError());return 0;}EventArray[EventTotal]=WSACreateEvent();ZeroMemory(&overlapped,sizeof(overlapped));overlapped.hEvent=EventArray[EventTotal];EventTotal++; wsabuf.buf=buffer;wsabuf.len=DATA_BUFFER;if ((WSARecv(sAccept,&wsabuf,1,&byteRecv,&Flags,&overlapped,NULL))==SOCKET_ERROR){if (WSAGetLastError()!=WSA_IO_PENDING){printf("Error occurred at WSARecv()\n");return 0;}}while(TRUE){DWORD index;index=WSAWaitForMultipleEvents(EventTotal,EventArray,FALSE,WSA_INFINITE,FALSE);WSAResetEvent(EventArray[index - WSA_WAIT_EVENT_0]);WSAGetOverlappedResult(sAccept, &overlapped,&ByteTranfer, FALSE, &Flags); //if the connection close,if so closesocket;if (ByteTranfer==0){printf("Closing Socket %d\n", sAccept);closesocket(sAccept);WSACloseEvent(EventArray[index - WSA_WAIT_EVENT_0]);return 0;}if (WSASend(sAccept, &wsabuf, 1, &byteRecv, Flags, &overlapped, NULL) == SOCKET_ERROR){ printf("WSASend() is busted\n");}//post another WSARecv on socket;Flags=0;ZeroMemory(&overlapped,sizeof(overlapped));overlapped.hEvent=EventArray[index-WSA_WAIT_EVENT_0];wsabuf.buf=buffer;wsabuf.len=DATA_BUFFER;if ((WSARecv(sAccept,&wsabuf,1,&byteRecv,&Flags,&overlapped,NULL))==SOCKET_ERROR){if (WSAGetLastError()!=WSA_IO_PENDING){printf("Error occurred at WSARecv()\n");return 0;}}}return 0;}
- winsock重叠IO模型
- WinSock IO模型---重叠模型
- WinSock重叠IO模型一
- winsock IO模型 重叠端口
- WinSock重叠IO模型一
- WinSock之CAsyncSocket模型与重叠IO模型(1)
- Winsock重叠模型
- winsock IO 模型---重叠IO之事件通知 example code
- WinSock IO模型四: 重叠I/O (事件通知)
- WinSock IO模型四: 重叠I/O (完成例程)
- WinSock重叠I/O模型
- winsock重叠iI/O模型
- winsock重叠iI/O模型
- winsock重叠iI/O模型
- winsock重叠iI/O模型
- WinSock重叠I/O模型
- WinSock重叠I/O模型
- WinSock 重叠I/O模型
- 域命令相关命令
- CF_320A.Magic Numbers
- Android中使用反射实现类似于C语言指针的调用
- 全民微博广告 13万家企业如何微博制胜
- uploadiy3.2_Java_Servlet_多文件上传
- WinSock IO模型---重叠模型
- 不用Map高效更新数据对应关系
- C++语法基础--public,protected,private的继承方式及其访问性
- android 反射应用
- Visio2010建立ER图并直接导出为SQL语句
- java线程安全问题之静态变量、实例变量、局部变量
- [leetcode]Remove Duplicates from Sorted List
- nyist-485
- android学习笔记---66_自定义标签页