[windows] IOCP底层,支持超过15000个连接

来源:互联网 发布:阿里云文档管理 编辑:程序博客网 时间:2024/04/19 22:13

From: http://blog.csdn.net/educast/article/details/14523457

#pragma comment(lib, "ws2_32.lib")#include <winsock2.h>#include <stdio.h>//////////////////////////////////////////////////////////////////////////// 仅供测试软件用#define DATA_BUFSIZE 1024        // 接收缓冲区大小typedef enum{ IOSEND,IORECV,IOQUIT } IO_TYPE;typedef struct _SOCKET_INFORMATION {OVERLAPPED Overlapped;SOCKET        Socket;IO_TYPE  IoType;charbuffer[DATA_BUFSIZE];WSABUFDataBuf;DWORD        BytesSEND;DWORD        BytesRECV;} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;DWORD   Flags = 0,Bytes = 0;DWORD WINAPI WorkThread(LPVOID CompletionPortID);DWORD WINAPI AcceptThread(LPVOID lpParameter){WSADATA wsaData;HANDLE hCompPort;DWORD ThreadID;DWORD Ret;if ((Ret = WSAStartup(0x0202, &wsaData)) != 0){printf("WSAStartup failed with error %d\n", Ret);return FALSE;}if ((hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL){printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError());return FALSE;}// 根据CPU个数来创建线程,以达到最佳性能SYSTEM_INFO SystemInfo;GetSystemInfo(&SystemInfo);printf("processors=%d\n", SystemInfo.dwNumberOfProcessors);for(unsigned int i=0; i<SystemInfo.dwNumberOfProcessors*2; i++){HANDLE ThreadHandle;if ((ThreadHandle = CreateThread(NULL, 0, WorkThread, hCompPort, 0, &ThreadID)) == NULL){printf("CreateThread() failed with error %d\n", GetLastError());return FALSE;}CloseHandle(ThreadHandle);}SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);SOCKADDR_IN ServerAddr;ServerAddr.sin_family = AF_INET;ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);ServerAddr.sin_port = htons(7999);bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));listen(ListenSocket,100);printf("listenning...\n");SOCKADDR_IN ClientAddr;int addr_length = sizeof(ClientAddr);while (TRUE){LPSOCKET_INFORMATION SI = new SOCKET_INFORMATION;if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET){printf("accept ip:%s port:%d\n",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);// 相关参数初始化memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));memset(SI->buffer, 0, DATA_BUFSIZE);SI->DataBuf.buf = SI->buffer;SI->DataBuf.len = DATA_BUFSIZE;SI->BytesRECV        = 0;SI->BytesSEND        = 0;SI->IoType           = IORECV;if (CreateIoCompletionPort((HANDLE)SI->Socket, hCompPort, (DWORD)SI, 0) == NULL){printf("CreateIoCompletionPort failed with error %d\n", GetLastError());return FALSE;}// 发出一个重叠I\O请求if(WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR){if(WSAGetLastError() != WSA_IO_PENDING){printf("disconnect\n");closesocket(SI->Socket);delete SI;continue;}}}}return FALSE;}DWORD WINAPI WorkThread(LPVOID CompletionPortID){HANDLE hCompPort = (HANDLE)CompletionPortID;while (TRUE){DWORD BytesTransferred = 0;LPSOCKET_INFORMATION SI = NULL;LPWSAOVERLAPPED Overlapped = NULL;// 线程进入线程池,等待被唤醒if (GetQueuedCompletionStatus(hCompPort, &BytesTransferred, (LPDWORD)&SI, &Overlapped, INFINITE)){if (0 == BytesTransferred && IOQUIT != SI->IoType){printf("disconnect\n");closesocket(SI->Socket); delete SI;continue;}switch(SI->IoType){case IORECV:{printf("%s \n", SI->buffer);// 目前的功能是将接收到的数据原封不动的返回SI->DataBuf.len = BytesTransferred;SI->BytesRECV = BytesTransferred;SI->IoType = IOSEND;if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR){if(WSAGetLastError() != WSA_IO_PENDING){printf("disconnect\n");closesocket(SI->Socket); delete SI;continue;}}break;}case IOSEND:{SI->BytesSEND += BytesTransferred;//返回是否彻底,若未发完,接着发if (SI->BytesSEND < SI->BytesRECV){SI->DataBuf.buf += BytesTransferred; SI->DataBuf.len -= BytesTransferred; SI->IoType = IOSEND;if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR){if(WSAGetLastError() != WSA_IO_PENDING){printf("disconnect\n");closesocket(SI->Socket); delete SI;continue;}}}else if (SI->BytesSEND > SI->BytesRECV){printf("BytesSEND:%d > BytesRECV:%d\n", SI->BytesSEND,SI->BytesRECV);memset(SI->buffer, 0, DATA_BUFSIZE);SI->BytesRECV = 0;SI->BytesSEND = 0;SI->IoType = IORECV;SI->DataBuf.len = DATA_BUFSIZE;SI->DataBuf.buf = SI->buffer;}else{memset(SI->buffer, 0, DATA_BUFSIZE);SI->BytesRECV = 0;SI->BytesSEND = 0;SI->IoType = IORECV;SI->DataBuf.len = DATA_BUFSIZE;SI->DataBuf.buf = SI->buffer;if (WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR){if(WSAGetLastError() != WSA_IO_PENDING){printf("disconnect\n");closesocket(SI->Socket); delete SI;continue;}}}break;}case IOQUIT:{// 让线程安全退出return FALSE;break;}default:break;}}        }        return FALSE;}void main()   {HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL);WaitForSingleObject(hThreads, INFINITE);printf("exit\n");CloseHandle(hThreads);} 

用VS2012 新建windows 控制台应用程序,空项目,新建文件main.cpp, 粘贴以上代码,直接编译,应该能通过。


0 0