【转】IOCP配合AcceptEx的例子
原文地址:http://laokaddk.blog.51cto.com/368606/610145/

本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。

#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>     //微软扩展的类库using namespace std;
#define SEND 0
#define RECV 1
#define ACCEPT 2#define DATA_LENGTH 1000
//单句柄数据定义
typedef struct _PER_HANDLE_DATA
{SOCKET socket;     //相关的套接字SOCKADDR_STORAGE clientAddr;     //客户端的地址
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;//但IO操作数据
typedef struct{OVERLAPPED overlapped;WSABUF buffer;     //一个数据缓冲区,用于WSASend/WSARecv中的第二个参数char dataBuffer[DATA_LENGTH];     //实际的数据缓冲区int dataLength;                     //实际的数据缓冲区长度int operatorType;                 //操作类型,可以为SEND/RECV两种SOCKET client;                     //分别表示发送的字节数和接收的字节数
}PER_IO_DATA,*LPPER_IO_DATA;void main()
{HANDLE CompletionPort;WSADATA data;SYSTEM_INFO info;SOCKADDR_IN addr;SOCKET Listen;unsigned int i;WSAStartup(MAKEWORD(2,2),&data);//创建一个IO完成端口CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);//确定处理器的数量GetSystemInfo(&info);     //创建线城for(i=0;i<info.dwNumberOfProcessors * 2;i++){//根据处理器的数量创建相应多的处理线程HANDLE thread = CreateThread(NULL,0,ServerThread,CompletionPort,0,NULL);CloseHandle(thread);}//创建一个监听套接字(进行重叠操作)Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);//将监听套接字与完成端口绑定LPPER_HANDLE_DATA perDandleData;perDandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));perDandleData->socket = Listen;CreateIoCompletionPort((HANDLE)Listen,CompletionPort,(ULONG_PTR)perDandleData,0);addr.sin_family = AF_INET;addr.sin_addr.s_addr = htonl(INADDR_ANY);addr.sin_port = htons(5500);bind(Listen,(PSOCKADDR)&addr,sizeof(addr));listen(Listen,5);LPFN_ACCEPTEX lpfnAcceptEx = NULL;     //AcceptEx函数指针//Accept function GUIDGUID guidAcceptEx = WSAID_ACCEPTEX;//get acceptex function pointerDWORD dwBytes = 0;if(WSAIoctl(Listen,SIO_GET_EXTENSION_FUNCTION_POINTER,&guidAcceptEx,sizeof(guidAcceptEx),&lpfnAcceptEx,sizeof(lpfnAcceptEx),&dwBytes,NULL,NULL)==0)cout<<"WSAIoctl success..."<<endl;else{cout<<"WSAIoctl failed..."<<endl;switch(WSAGetLastError()){case WSAENETDOWN:cout<<""<<endl;break;case WSAEFAULT:cout<<"WSAEFAULT"<<endl;break;case WSAEINVAL:cout<<"WSAEINVAL"<<endl;break;case WSAEINPROGRESS:cout<<"WSAEINPROGRESS"<<endl;break;case WSAENOTSOCK:cout<<"WSAENOTSOCK"<<endl;break;case WSAEOPNOTSUPP:cout<<"WSAEOPNOTSUPP"<<endl;break;case WSA_IO_PENDING:cout<<"WSA_IO_PENDING"<<endl;break;case WSAEWOULDBLOCK:cout<<"WSAEWOULDBLOCK"<<endl;break;case WSAENOPROTOOPT:cout<<"WSAENOPROTOOPT"<<endl;break;}return;}//while(true)//{//准备调用 AcceptEx 函数,该函数使用重叠结构并于完成端口连接LPPER_IO_DATA perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));    perIoData->operatorType = ACCEPT;//在使用AcceptEx前需要事先重建一个套接字用于其第二个参数。这样目的是节省时间//通常可以创建一个套接字库perIoData->client = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);perIoData->dataLength = DATA_LENGTH;DWORD flags = 0;//调用AcceptEx函数,地址长度需要在原有的上面加上16个字节//注意这里使用了重叠模型,该函数的完成将在与完成端口关联的工作线程中处理cout<<"Process AcceptEx function wait for client connect..."<<endl;int rc = lpfnAcceptEx(Listen,perIoData->client,perIoData->dataBuffer,perIoData->dataLength-((sizeof(SOCKADDR_IN)+16)*2),sizeof(SOCKADDR_IN)+16,sizeof(SOCKADDR_IN)+16,&dwBytes,&(perIoData->overlapped));if(rc == FALSE){if(WSAGetLastError()!=ERROR_IO_PENDING)cout<<"lpfnAcceptEx failed.."<<endl;}cin>>i;closesocket(Listen);WSACleanup();
}DWORD WINAPI ServerThread(LPVOID lpParam)
{HANDLE CompletionPort = (HANDLE)lpParam;DWORD bytes;LPPER_HANDLE_DATA perHandleData = NULL;     //单句柄数据LPPER_IO_DATA perIoData;             //单IO数据DWORD Flags;int ret;DWORD RecvBytes;//进入循环的等待重叠操作的完成while(true){bytes = -1;ret=GetQueuedCompletionStatus(CompletionPort,                 //原先的完成端口句柄&bytes,                         //重叠操作完成的字节数(LPDWORD)&perHandleData,     //原先和完成端口句柄关联起来的单句柄数据(LPOVERLAPPED*)&perIoData,     //用于接收已完成的IO操作的重叠结构INFINITE);                     //在完成端口上等待的时间 INFINITE 为无限等待//先检查在套接字上是否发生错误//当发生错误时关闭套接字同时释放掉所有的内存.int i = 0;if(bytes == 0 && (perIoData->operatorType == RECV ||perIoData->operatorType == SEND)){closesocket(perHandleData->socket);GlobalFree(perHandleData);GlobalFree(perIoData);cout<<"closesocket and globalfree perhandledata periodata!"<<endl;continue;}//这是AcceptEx函数处理完成,在下面处理if(perIoData->operatorType == ACCEPT)     //处理连接操作{//使用GetAcceptExSockaddrs函数 获得具体的各个地址参数.if(setsockopt( perIoData->client, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,  ( char* )&(perHandleData->socket ), sizeof( perHandleData->socket ) )==SOCKET_ERROR)cout<<"setsockopt..."<<endl;perHandleData->socket = perIoData->client;//memcpy(&(perHandleData->clientAddr),raddr,sizeof(raddr));//将新的客户套接字与完成端口连接CreateIoCompletionPort((HANDLE)perHandleData->socket,CompletionPort,(ULONG_PTR)perHandleData,0);memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));perIoData->operatorType = RECV;         //将状态设置成接收//设置WSABUF结构perIoData->buffer.buf = perIoData->dataBuffer;perIoData->buffer.len = perIoData->dataLength = DATA_LENGTH;cout<<"wait for data arrive(Accept)..."<<endl;Flags = 0;if(WSARecv(perHandleData->socket,&(perIoData->buffer),1,&RecvBytes,&Flags,&(perIoData->overlapped),NULL)==SOCKET_ERROR)if(WSAGetLastError()==WSA_IO_PENDING)cout<<"WSARecv Pending..."<<endl;continue;            }if(perIoData->operatorType == RECV)cout<<perIoData->buffer.buf<<endl;     //将接收到的数据显示出来Flags = 0;perIoData->operatorType = RECV;             //设置成接受数据类型ZeroMemory(&(perIoData->overlapped),sizeof(OVERLAPPED));//重新投递一个新的接收请求cout<<" wait for data arrive..."<<endl;WSARecv(perHandleData->socket,&(perIoData->buffer),1,&RecvBytes,&Flags,&(perIoData->overlapped),NULL);}return 0;}

【转】IOCP配合AcceptEx的例子相关推荐

  1. IOCP配合AcceptEx的例子

    本程序在VS2003编译器编译运行.在6.0下可能需要稍加修改. #include <iostream> #include <winsock2.h> #include < ...

  2. iocp配合acceptex

    摘自网上: IOCP配合AcceptEx的例子(1)(发表时间: 2006-7-2 14:33:00) [评论] [打印] [字体:大 中 小] 本文链接:http://blog.pfan.cn/ma ...

  3. IOCP结合AcceptEx实例

    在普通IOCP的基础上注意两点: 1.记得把监听socket绑定到端口 2.在Accept处理过程中,抛出接受连接的AcceptEx请求,绑定客户端socket到端口和抛出recv请求 客户端要断开连 ...

  4. IOCP之AcceptEx的问题(1)

    最近在使用编写IOCP模型时,Server端使用的是AcceptEx异步 而Client端是用的Socket函数,但是在测试中遇到这种情况: CLient并发连接到Server,每次都是连接数1635 ...

  5. IOCP使用acceptEX进行异步接收

    示例代码为什么要调用WSAIoctl ()函数 #include <winsock2.h> #include <windows.h> #include <string&g ...

  6. IOCP使用acceptEx产生997错误

    997错误在解释中是重叠IO正在使用中,要么使用acceptEx没有开线程,一些结果没办法处理,要么就是在x64位系统编译中出现的问题.第二种可能 性最大.还在解决了,解决了再来更新 CSDN上对99 ...

  7. uicolor swift_Swift中的UIColor

    uicolor swift UIColor (UIColor) An object that stores color data and sometimes opacity. 存储颜色数据和有时不透明 ...

  8. IOCP扩展方法AcceptEx, DisconnectEx, GetAcceptExSockaddr用法示例

    这篇文章记录了我刚接触IOCP模型时的理解,对于初学者,应该算不错的调试程序,仅有一个400多行代码的dpr文件,可以直接用WriteLn输出信息,前提是会用delphi建立Console Appli ...

  9. 完成端口与AcceptEx

    关于IOCP网上到处都是资料,说的也很详细.我在这里就不再多说了,这只是本人在学习IOCP时的笔记,和配合AcceptEx写的一个极小的服务端程序.由于刚刚接触ICOP加上本人刚毕业不到一年,所以里面 ...

最新文章

  1. ArduinoYun的电源插座
  2. virilog 模块之间的层次关系_软件工程导论 期末复习题
  3. Orecle基本概述(2)
  4. centos7下使用yum安装mysql
  5. Windows和Linux如何使用Java代码实现关闭进程
  6. Linux中重定向及管道,Linux中重定向及管道
  7. android 通知灯 测试,Android灯光系统通知灯【转】
  8. Bootstrap 插件的选项
  9. 2680 Problem F: Coin Game
  10. 一键关闭服务器危险端口BAT文件安防篇
  11. linux 文件系统的简单操作
  12. root魅族android6,魅族PRO6怎么ROOT ROOT权限获取方法教程
  13. 计算机科学之父图灵的一生
  14. 计算机应届博士生的一点求职经验——概述篇
  15. T3批次结存表和库存台账和现存量数量不一致
  16. 使用N2N,实现异地快速组建内网
  17. 应届生求职前端工程师岗位,该如何准备?
  18. youwuku和koudaitong以及weimeng差异
  19. 囚徒困境困境_社会困境两部恐怖电影主演
  20. css 高度塌陷_高度塌陷问题_前端技术文章 - SegmentFault 思否

热门文章

  1. [答疑]茶叶盒的用例
  2. 开源办公套件 ONLYOFFICE文档7.4新功能
  3. JPA - Persistence与EntityManagerFactory
  4. 土地荒漠化遥感数据处理与分析
  5. Vue基础知识+组件化开发+模块化开发总结
  6. java全月应纳税所得额_个人所得税应纳税所得额计算公式是什么?
  7. 100个黑球和100个白球问题
  8. containskey java_Java Hashtable containsKey()方法与示例
  9. CSS3基础入门02
  10. 大量的用伪元素可以实现的奇妙效果