| #include?<winsock2.h> #include?<stdio.h> #define?PORT 5150 #define?MSGSIZE 1024 #pragma?comment(lib,?"ws2_32.lib") typedef?struct { ?WSAOVERLAPPED overlap;//為了使用重疊I/O,每一個(gè)I/O函數(shù)都要接受一個(gè)WSAOVERLAPPED結(jié)構(gòu)類型的參數(shù) ?WSABUF Buffer; ?char?szMessage[MSGSIZE]; ?DWORD NumberOfBytesRecvd; ?DWORD Flags; }PER_IO_OPERATION_DATA,?*LPPER_IO_OPERATION_DATA; int?g_iTotalConn?=?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); void?Cleanup(int); int?main() { ?WSADATA wsaData; ?SOCKET?sListen,?sClient; ?SOCKADDR_IN?local,?client; ?DWORD dwThreadId; ?int?iaddrSize?=?sizeof(SOCKADDR_IN); ?// Initialize Windows Socket library ?WSAStartup(0x0202,?&wsaData); ?// Create listening socket ?sListen?=?::WSASocket(AF_INET,?SOCK_STREAM,?IPPROTO_TCP,NULL,0,WSA_FLAG_OVERLAPPED); ?// Bind ?local.sin_addr.S_un.S_addr?=?htonl(INADDR_ANY); ?local.sin_family?=?AF_INET; ?local.sin_port?=?htons(PORT); ?bind(sListen,?(struct?sockaddr?*)&local,?sizeof(SOCKADDR_IN)); ?// Listen ?listen(sListen,?3); ?// Create worker thread ?CreateThread(NULL,?0,?WorkerThread,?NULL,?0,?&dwThreadId); ?while?(TRUE) ?{ ??// Accept a connection ??sClient?=?accept(sListen,?(struct?sockaddr?*)&client,?&iaddrSize); ??printf("Accepted client:%s:%d\n",?inet_ntoa(client.sin_addr),?ntohs(client.sin_port)); ??g_CliSocketArr[g_iTotalConn]?=?sClient; ??// Allocate a PER_IO_OPERATION_DATA structure ??g_pPerIODataArr[g_iTotalConn]?=?(LPPER_IO_OPERATION_DATA)HeapAlloc( ???GetProcessHeap(), ???HEAP_ZERO_MEMORY, ???sizeof(PER_IO_OPERATION_DATA)); ??g_pPerIODataArr[g_iTotalConn]->Buffer.len?=?MSGSIZE; ??g_pPerIODataArr[g_iTotalConn]->Buffer.buf?=?g_pPerIODataArr[g_iTotalConn]->szMessage; ??g_CliEventArr[g_iTotalConn]?=?g_pPerIODataArr[g_iTotalConn]->overlap.hEvent?=?WSACreateEvent(); ??// Launch an asynchronous operation(發(fā)起一個(gè)異步的I/O操作) ??//This function receives data from a connected socket. ??WSARecv( ???g_CliSocketArr[g_iTotalConn],//Socket的標(biāo)示 ???&g_pPerIODataArr[g_iTotalConn]->Buffer,//接收數(shù)據(jù)的Buffer ???1, ???&g_pPerIODataArr[g_iTotalConn]->NumberOfBytesRecvd,//Pointer to the number of bytes received by this call if the receive operation completes immediately ???&g_pPerIODataArr[g_iTotalConn]->Flags, ???&g_pPerIODataArr[g_iTotalConn]->overlap,//LPWSAOVERLAPPED結(jié)構(gòu)的參數(shù) ???NULL); ??g_iTotalConn++; ?} ?closesocket(sListen); ?WSACleanup(); ?return?0; } DWORD WINAPI WorkerThread(LPVOID lpParam) { ?int?ret,?index; ?DWORD cbTransferred; ?while?(TRUE) ?{ ??ret?=?WSAWaitForMultipleEvents(g_iTotalConn,?g_CliEventArr,?FALSE,?1000,?FALSE); ??//注意這里應(yīng)該有相應(yīng)的修正的地方,WSAWaitForMultipleEvents函數(shù)在fWaitAll設(shè)置成FALSE ??//的時(shí)候只能指定一個(gè)事件對(duì)象受信,解決方法使用for循環(huán)進(jìn)行循環(huán)檢測(cè) ??if?(ret?==?WSA_WAIT_FAILED?||?ret?==?WSA_WAIT_TIMEOUT) ??{ ???continue; ??} ??index?=?ret?-?WSA_WAIT_EVENT_0; ??WSAResetEvent(g_CliEventArr[index]); ??//獲得重疊I/O的操作的結(jié)果 ??WSAGetOverlappedResult( ???g_CliSocketArr[index], ???&g_pPerIODataArr[index]->overlap, ???&cbTransferred, ???TRUE, ???&g_pPerIODataArr[g_iTotalConn]->Flags); ??if?(cbTransferred?==?0) ??{ ???// The connection was closed by client ???Cleanup(index); ??} ??else ??{ ???// g_pPerIODataArr[index]->szMessage contains the received data ???g_pPerIODataArr[index]->szMessage[cbTransferred]?=?'\0'; ???//這個(gè)是同步的I/O的操作哦 ???send(g_CliSocketArr[index],?g_pPerIODataArr[index]->szMessage,\ ????cbTransferred,?0); ???// Launch another asynchronous operation ???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_iTotalConn?-?1) ?{ ??g_CliSocketArr[index]?=?g_CliSocketArr[g_iTotalConn?-?1]; ??g_CliEventArr[index]?=?g_CliEventArr[g_iTotalConn?-?1]; ??g_pPerIODataArr[index]?=?g_pPerIODataArr[g_iTotalConn?-?1]; ?} ?g_pPerIODataArr[--g_iTotalConn]?=?NULL; } |