IOCP例子二

来源:互联网 发布:win10ie无法下载软件 编辑:程序博客网 时间:2024/06/03 16:10
#include <winsock2.h>#include <Mswsock.h>#include <stdio.h>#include <windows.h>#include <assert.h>#include <list>#pragma comment(lib, "ws2_32.lib")#pragma comment(lib,"Mswsock.lib")using namespace std;LONG volatileg_ThreadNum;//线程数目HANDLEg_hCompletion;// SOCKETg_socket;//sock #defineBUFFER_SIZE20480//最大缓冲enum IO_TYPE {IO_TYPE_ACCEPT,//网络连接IO_TYPE_READ,//网络读取IO_TYPE_WRITE,//网络写入IO_TYPE_UNKNOWN//无效类型};#pragma pack(1)struct OverLappedEx {OVERLAPPEDm_OLap;IO_TYPEm_IOType;//IO请求类型charm_szBuf[BUFFER_SIZE];//接收缓冲OverLappedEx(IO_TYPE ioType){ZeroMemory(&m_OLap, sizeof(OVERLAPPED));ZeroMemory(m_szBuf, BUFFER_SIZE);m_IOType = ioType;}};struct PerSocketData {SOCKET   m_Socket;SOCKET m_AccSocket;PerSocketData(){m_Socket = INVALID_SOCKET;m_AccSocket = INVALID_SOCKET;}};#pragma pack()list <PerSocketData *> g_ArrSocketData;list <OverLappedEx *> g_ArrOverLapEx;PerSocketData *AssignSockToCompletionPort(SOCKET tSocket){assert(tSocket != INVALID_SOCKET);PerSocketData *pSockData = new PerSocketData();pSockData->m_Socket = tSocket;g_ArrSocketData.push_back(pSockData);CreateIoCompletionPort((HANDLE)tSocket, g_hCompletion, (ULONG_PTR)pSockData, 0);return pSockData;}BOOL PostAccept(PerSocketData *pSockData){DWORD dwBytesRecv = 0;assert(pSockData != NULL);OverLappedEx *m_pOverLap = new OverLappedEx(IO_TYPE_ACCEPT);g_ArrOverLapEx.push_back(m_pOverLap);pSockData->m_AccSocket = WSASocket(AF_INET , SOCK_STREAM , IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);BOOL bRet = AcceptEx(pSockData->m_Socket, pSockData->m_AccSocket, m_pOverLap->m_szBuf, 0, sizeof(sockaddr_in)+16, sizeof(sockaddr_in)+16, &dwBytesRecv, &m_pOverLap->m_OLap);if (!bRet){if (WSAGetLastError() != WSA_IO_PENDING) {return FALSE;}}return TRUE;}BOOL PostRecv(PerSocketData *pSockData){assert(pSockData != NULL);WSABUF wsaBuf = {0};OverLappedEx *m_pOverLap = new OverLappedEx(IO_TYPE_READ);g_ArrOverLapEx.push_back(m_pOverLap);wsaBuf.buf = m_pOverLap->m_szBuf;wsaBuf.len = BUFFER_SIZE;DWORD dwBytesRecv = 0, dwFlags = 0;int iRet = WSARecv(pSockData->m_Socket, &wsaBuf, 1, &dwBytesRecv, &dwFlags, &(m_pOverLap->m_OLap), NULL);if (iRet != NO_ERROR){if (WSAGetLastError() != WSA_IO_PENDING){return FALSE;}}return TRUE;}DWORD WINAPI ServerThread(LPVOID lpParam){//参数效验assert(lpParam!=NULL);if (lpParam==NULL)return FALSE;//定义变量 HANDLE hCompletion = (HANDLE)lpParam;OverLappedEx *pOverLaps = NULL;PerSocketData *pPerSockData = NULL;DWORD dwTrans = 0;BOOL bOK=FALSE; InterlockedIncrement(&g_ThreadNum);while(TRUE){// 在关联到此完成端口的所有套节字上等待I/O完成bOK= GetQueuedCompletionStatus(hCompletion, &dwTrans, (LPDWORD)&pPerSockData, (LPOVERLAPPED*)&pOverLaps, INFINITE);//收到关闭通知if (pPerSockData==NULL || pOverLaps==NULL) break;// 在此套节字上有错误发生if(bOK==FALSE)continue;// 套节字被对方关闭if(dwTrans == 0 &&  pOverLaps!=NULL &&(pOverLaps->m_IOType == IO_TYPE_READ || pOverLaps->m_IOType == IO_TYPE_WRITE)){closesocket(pPerSockData->m_Socket);g_ArrSocketData.remove(pPerSockData);g_ArrOverLapEx.remove(pOverLaps);delete pPerSockData;delete pOverLaps;pPerSockData=NULL;pOverLaps=NULL;continue;}switch(pOverLaps->m_IOType){case IO_TYPE_READ://网络读取{PostRecv(pPerSockData);printf("收到客户端数据:%s\n",pOverLaps->m_szBuf);DWORD dwSend = 0;OverLappedEx *pOverLapEx = NULL;pOverLapEx = new OverLappedEx(IO_TYPE_WRITE);memcpy_s(pOverLapEx->m_szBuf, BUFFER_SIZE, "这是服务端发送的消息", ARRAYSIZE("这是服务端发送的消息"));WSABUF wsaBuf = {0};wsaBuf.buf = pOverLapEx->m_szBuf;wsaBuf.len = ARRAYSIZE("这是服务端发送的消息");g_ArrOverLapEx.push_back(pOverLapEx);//针对单个客户端发//WSASend(pPerSockData->m_Socket, &wsaBuf, 1, &dwSend, 0, &(pOverLapEx->m_OLap), NULL);//所有客户端群发list<PerSocketData*>::const_iterator cIterSocke;  for (cIterSocke = g_ArrSocketData.begin(); cIterSocke != g_ArrSocketData.end(); cIterSocke++)  {//过滤自己if ((*cIterSocke)->m_Socket==g_socket)continue;WSASend((*cIterSocke)->m_Socket, &wsaBuf, 1, &dwSend, 0, &(pOverLapEx->m_OLap), NULL);}g_ArrOverLapEx.remove(pOverLaps);if (pOverLaps){delete pOverLaps;pOverLaps =NULL;}}break;case IO_TYPE_WRITE:{g_ArrOverLapEx.remove(pOverLaps);if (pOverLaps){delete pOverLaps;pOverLaps =NULL;}}break;case IO_TYPE_ACCEPT:{if (pPerSockData->m_AccSocket == INVALID_SOCKET)continue;PerSocketData *pData = AssignSockToCompletionPort(pPerSockData->m_AccSocket);PostRecv(pData);PostAccept(pPerSockData);g_ArrOverLapEx.remove(pOverLaps);if (pOverLaps){delete pOverLaps;pOverLaps =NULL;}}break;default:break;}}InterlockedDecrement(&g_ThreadNum);return 0;}//启动服务DWORD ThreadProc(  LPVOID lpParameter){//设置变量g_ThreadNum=0;int nPort = 4567;//创建完成端口对象g_hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);// 创建监听套节字g_socket = WSASocket(AF_INET , SOCK_STREAM , IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);assert(g_socket!=INVALID_SOCKET);if (g_socket==INVALID_SOCKET)return FALSE;//绑定端口SOCKADDR_IN  ServerAddr;ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = ntohs(nPort);ServerAddr.sin_addr.S_un.S_addr = INADDR_ANY;if (bind(g_socket, (sockaddr*)&ServerAddr, sizeof(ServerAddr))==SOCKET_ERROR){assert(FALSE);return FALSE;}//监听listen(g_socket, SOMAXCONN);//关联套接字PerSocketData *pSockData = AssignSockToCompletionPort(g_socket);//队列工作项在线程池中的工作线程QueueUserWorkItem(ServerThread, g_hCompletion, WT_EXECUTELONGFUNCTION);PostAccept(pSockData);return TRUE;}int main(void){// 初始化WS2_32.dllWSADATA wsaData;WORD sockVersion = MAKEWORD(2, 0);WSAStartup(sockVersion, &wsaData);//启动服务CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,NULL,NULL);getchar();//清理线程工作while(g_ThreadNum > 0){PostQueuedCompletionStatus(g_hCompletion, 0, 0, NULL);Sleep(100);} list<PerSocketData*>::const_iterator cIterSocke;   for (cIterSocke = g_ArrSocketData.begin(); cIterSocke != g_ArrSocketData.end(); cIterSocke++)   { closesocket((*cIterSocke)->m_Socket); delete *cIterSocke; } g_ArrSocketData.clear(); list<OverLappedEx*>::const_iterator cIter;   for (cIter = g_ArrOverLapEx.begin(); cIter != g_ArrOverLapEx.end(); cIter++)   { delete *cIter; } g_ArrOverLapEx.clear();CloseHandle(g_hCompletion); WSACleanup();return 0;}

0 0