实现基于IOCP的回声服务器端
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <process.h> 4 #include <winsock2.h> 5 #include <windows.h> 6 7 #define BUF_SIZE 1024 8 #define READ 3 9 #define WRITE 5 10 11 typedef struct //socket info 12 { 13 SOCKET hClntSock; 14 SOCKADDR_IN clntAdr; 15 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA; 16 17 typedef struct //buffer info 18 { 19 OVERLAPPED overlapped; 20 WSABUF wsaBuf; 21 char buffer[BUF_SIZE]; 22 int rwMode; // READ or WRITE 23 }PER_IO_DATA, *LPPER_IO_DATA; 24 25 unsigned WINAPI EchoThreadMain(LPVOID CompletionPortIO); 26 void ErrorHanding(char *msg); 27 28 int main(int argc, char *argv[]) 29 { 30 WSADATA wsaData; 31 HANDLE hComPort; 32 SYSTEM_INFO sysInfo; 33 LPPER_IO_DATA ioInfo; 34 LPPER_HANDLE_DATA handleInfo; 35 36 SOCKET hServSock; 37 SOCKADDR_IN servAdr; 38 int recvBytes, i, flags = 0; 39 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 40 ErrorHanding("WSAStartUp() error!"); 41 42 hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); 43 GetSystemInfo(&sysInfo); 44 for (i = 0; i < sysInfo.dwNumberOfProcessors; i++) 45 _beginthreadex(NULL, 0, EchoThreadMain, (LPVOID)hComPort, 0, NULL); 46 47 hServSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 48 memset(&servAdr, 0, sizeof(servAdr)); 49 servAdr.sin_family = AF_INET; 50 servAdr.sin_addr.s_addr = htonl(INADDR_ANY); 51 servAdr.sin_port = htons(atoi(argv[1])); 52 53 bind(hServSock, (SOCKADDR *)&servAdr, sizeof(servAdr)); 54 listen(hServSock, 5); 55 56 while (1) 57 { 58 SOCKET hClntSock; 59 SOCKADDR_IN clntAdr; 60 int addrLen = sizeof(clntAdr); 61 62 hClntSock = accept(hServSock, (SOCKADDR *)&servAdr, &addrLen); 63 handleInfo = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA)); 64 handleInfo->hClntSock = hClntSock; 65 memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen); 66 67 CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, 0); 68 69 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); 70 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 71 ioInfo->wsaBuf.len = BUF_SIZE; 72 ioInfo->wsaBuf.buf = ioInfo->buffer; 73 ioInfo->rwMode = READ; 74 WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf), 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &(ioInfo->overlapped), NULL); 75 } 76 return 0; 77 } // end of main function 78 79 unsigned WINAPI EchoThreadMain(LPVOID pComPort) 80 { 81 HANDLE hComPort = (HANDLE)pComPort; 82 SOCKET sock; 83 DWORD bytesTrans; 84 LPPER_HANDLE_DATA handleInfo; 85 LPPER_IO_DATA ioInfo; 86 DWORD flags = 0; 87 88 while (1) 89 { 90 GetQueuedCompletionStatus(hComPort, &bytesTrans, (LPDWORD) &handleInfo, (LPOVERLAPPED *) &ioInfo, INFINITE); 91 sock = handleInfo->hClntSock; 92 93 if (ioInfo->rwMode == READ) 94 { 95 puts("message received!"); 96 if (bytesTrans == 0) 97 { 98 closesocket(sock); 99 free(handleInfo); 100 free(ioInfo); 101 continue; 102 } 103 104 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 105 ioInfo->wsaBuf.len = bytesTrans; 106 ioInfo->rwMode = WRITE; 107 WSASend(sock, &(ioInfo->wsaBuf), 1, NULL, 0, &(ioInfo->overlapped), NULL); 108 109 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); 110 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 111 ioInfo->wsaBuf.len = BUF_SIZE; 112 ioInfo->wsaBuf.buf = ioInfo->buffer; 113 ioInfo->rwMode = READ; 114 WSARecv(sock, &(ioInfo->wsaBuf), 1, NULL, &flags, &(ioInfo->overlapped), NULL); 115 } 116 else 117 { 118 puts("message sent!"); 119 free(ioInfo); 120 } 121 } 122 return 0; 123 } 124 125 void ErrorHanding(char *msg) 126 { 127 fputs(msg, stderr); 128 fputc('\n', stderr); 129 exit(1); 130 }