1. 程式人生 > >AcceptEx函數與完成端口的結合使用例子

AcceptEx函數與完成端口的結合使用例子

gre lean edit 調用 targe 老師 oda close tle

分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!http://www.captainbed.net

這是在學《Windows網絡編程(第二版)》第六章時制作的一個例子
由於書中沒有給出簡潔的例子,本人在學這裏時就費了很多時間。
現在把完成的代碼貼出來,供大家參考。
下面包括了主程序部分,工作線程在(2)中貼出,由於代碼太長。
本程序在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 GUID GUID guidAcceptEx = WSAID_ACCEPTEX; //get acceptex function pointer DWORD 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(); }

再分享一下我老師大神的人工智能教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智能的隊伍中來!http://www.captainbed.net

AcceptEx函數與完成端口的結合使用例子