重叠IO
// 重叠IO网络模式.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<WinSock2.h> #include<windows.h> #include<iostream> using namespace std; #pragma comment (lib,"ws2_32.lib") #define PORT 6000 #define MSGSIZE 1024 typedef struct { WSAOVERLAPPED overlap; WSABUF Buffer; char szMessage[MSGSIZE]; DWORD NumberOfBytesRecvd; DWORD Flags; }PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA; int g_iToalComn = 0; SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS]; WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS]; LPPER_IO_OPERATION_DATA g_pPerIODataArr[MAXIMUM_WAIT_OBJECTS]; DWORD WINAPI WorkerThread(LPVOID lparam); void Cleanup(int); bool InitNetEvn() { WSADATA wsa; if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { cout << "网络环境失败" << endl; return false; } if (LOBYTE(wsa.wVersion)!=2||HIBYTE(wsa.wVersion)!=2) { cout << "版本号不对" << endl; return false; } return true; } int main() { SOCKET sListen, sClient; SOCKADDR_IN local, client; DWORD dwThreadId; int iaddrSize = sizeof(SOCKADDR_IN); if (!InitNetEvn()) { return -1; } sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); local.sin_addr.S_un.S_addr = htonl(INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons(PORT); bind(sListen, (sockaddr *)&local, iaddrSize); listen(sListen, 3); CreateThread(NULL, NULL, WorkerThread, NULL, NULL, &dwThreadId); while (TRUE) { sClient = accept(sListen, (sockaddr *)&client, &iaddrSize); printf("Accept client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port)); g_CliSocketArr[g_iToalComn] = sClient; g_pPerIODataArr[g_iToalComn] = (LPPER_IO_OPERATION_DATA)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_OPERATION_DATA)); g_pPerIODataArr[g_iToalComn]->Buffer.len = MSGSIZE; g_pPerIODataArr[g_iToalComn]->Buffer.buf = g_pPerIODataArr[g_iToalComn]->szMessage; g_CliEventArr[g_iToalComn] = g_pPerIODataArr[g_iToalComn]->overlap.hEvent = WSACreateEvent(); WSARecv( g_CliSocketArr[g_iToalComn], &g_pPerIODataArr[g_iToalComn]->Buffer, 1, &g_pPerIODataArr[g_iToalComn]->NumberOfBytesRecvd, &g_pPerIODataArr[g_iToalComn]->Flags, &g_pPerIODataArr[g_iToalComn]->overlap, NULL); g_iToalComn++; } closesocket(sListen); WSACleanup(); return 0; } DWORD WINAPI WorkerThread(LPVOID lparam) { int ret, index; DWORD cbTransferred; while (true) { //判断出一个重叠IO调用是否完成 ret = WSAWaitForMultipleEvents(g_iToalComn, g_CliEventArr, FALSE, 1000, FALSE); if (ret==WSA_WAIT_TIMEOUT||ret==WSA_WAIT_FAILED) { continue; } index = ret - WSA_WAIT_EVENT_0; WSAResetEvent(g_CliEventArr[index]); WSAGetOverlappedResult( g_CliSocketArr[index], &g_pPerIODataArr[index]->overlap, &cbTransferred, TRUE, &g_pPerIODataArr[index]->Flags); if (cbTransferred==0) { Cleanup(index); } else { g_pPerIODataArr[index]->szMessage[cbTransferred] = '\0'; send(g_CliSocketArr[index], g_pPerIODataArr[index]->szMessage, \ cbTransferred, 0); WSARecv( g_CliSocketArr[index], &g_pPerIODataArr[index]->Buffer, 1, &g_pPerIODataArr[index]->NumberOfBytesRecvd, &g_pPerIODataArr[index]->Flags, &g_pPerIODataArr[index]->overlap, NULL); } } return 0; } void Cleanup(int index) { closesocket(g_CliSocketArr[index]); WSACloseEvent(g_CliEventArr[index]); HeapFree(GetProcessHeap(), 0, g_pPerIODataArr[index]); if (index<g_iToalComn-1) { g_CliSocketArr[index] = g_CliSocketArr[g_iToalComn - 1]; g_CliEventArr[index] = g_CliEventArr[g_iToalComn - 1]; g_pPerIODataArr[index] = g_pPerIODataArr[g_iToalComn - 1]; } g_pPerIODataArr[--g_iToalComn] = NULL; }