IOCP以及扩展Windows socket函数应用示例

来源:互联网 发布:如何购买淘宝店铺模板 编辑:程序博客网 时间:2024/06/06 00:51
#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();} 

原创粉丝点击