#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; char buffer[DATA_BUFSIZE]; WSABUF DataBuf; 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); 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); }