一、重叠I/O回声服务器端
服务端:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <WinSock2.h> 4 5 #define BUF_SIZE 1024 6 void ErrorHandling(char *message); 7 void CALLBACK ReadCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); 8 void CALLBACK WriteCompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); 9 10 typedef struct 11 { 12 SOCKET hClntSock; 13 char buf[BUF_SIZE]; 14 WSABUF wsaBuf; 15 }PER_IO_DATA, *LPPER_IO_DATA; 16 17 int main(int argc, char *argv[]) 18 { 19 if (argc != 2) { 20 printf("Usage : %s <port> ", argv[0]); 21 exit(1); 22 } 23 24 WSADATA wsaData; 25 SOCKET hLinSock, hRecvSock; 26 SOCKADDR_IN lisnAdr, recvAdr; 27 LPWSAOVERLAPPED lpOvLp; 28 DWORD recvBytes; 29 LPPER_IO_DATA hbInfo; 30 int mode = 1, recvAdrSz, flagInfo = 0; 31 32 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 33 ErrorHandling("WSAStartup() error."); 34 35 hLinSock = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 36 ioctlsocket(hLinSock, FIONBIO, (u_long*)&mode); // 套接字改成非阻塞的 37 38 memset(&lisnAdr, 0, sizeof(lisnAdr)); 39 lisnAdr.sin_family = AF_INET; 40 lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY); 41 lisnAdr.sin_port = htons(atoi(argv[1])); 42 43 if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR) 44 ErrorHandling("bind() error."); 45 if (listen(hLinSock, 5) == SOCKET_ERROR) 46 ErrorHandling("listen() error."); 47 printf("Server start... "); 48 recvAdrSz = sizeof(recvAdr); 49 while (1) 50 { 51 SleepEx(100, TRUE); // 让线程处于等待接收操作系统消息的线程状态 52 hRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz); 53 if (hRecvSock == INVALID_SOCKET){ 54 if (WSAGetLastError() == WSAEWOULDBLOCK) 55 continue; 56 else 57 ErrorHandling("accept() error"); 58 } 59 puts("Client connected..."); 60 61 lpOvLp = (LPWSAOVERLAPPED)malloc(sizeof(WSAOVERLAPPED)); 62 memset(lpOvLp, 0, sizeof(lpOvLp)); 63 64 hbInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); 65 hbInfo->hClntSock = (DWORD)hRecvSock; 66 (hbInfo->wsaBuf).buf = hbInfo->buf; 67 (hbInfo->wsaBuf).len = BUF_SIZE; 68 69 lpOvLp->hEvent = (HANDLE)hbInfo; 70 WSARecv(hRecvSock, &(hbInfo->wsaBuf), 1, &recvBytes, (LPDWORD)&flagInfo, lpOvLp, ReadCompRoutine); 71 } 72 closesocket(hRecvSock); 73 closesocket(hLinSock); 74 WSACleanup(); 75 return 0; 76 } 77 78 void CALLBACK ReadCompRoutine(DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags) 79 { 80 LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent); 81 SOCKET hSock = hbInfo->hClntSock; 82 LPWSABUF bufInfo = &(hbInfo->wsaBuf); 83 DWORD sentBytes; 84 85 if (szRecvBytes == 0) 86 { 87 closesocket(hSock); 88 free(hbInfo); 89 free(lpOverlapped); 90 puts("Client disconnected..."); 91 } 92 else 93 { 94 bufInfo->len = szRecvBytes; 95 WSASend(hSock, bufInfo, 1, &sentBytes, 0, lpOverlapped, WriteCompRoutine); 96 } 97 } 98 99 void CALLBACK WriteCompRoutine(DWORD dwError, DWORD szSendBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags) 100 { 101 LPPER_IO_DATA hbInfo = (LPPER_IO_DATA)(lpOverlapped->hEvent); 102 SOCKET hSock = hbInfo->hClntSock; 103 LPWSABUF bufInfo = &(hbInfo->wsaBuf); 104 DWORD recvBytes; 105 int flagInfo = 0; 106 WSARecv(hSock, bufInfo, 1, &recvBytes, (LPDWORD)&flagInfo, lpOverlapped, ReadCompRoutine); 107 } 108 109 void ErrorHandling(char *message) { 110 fputs(message, stderr); 111 fputc(' ', stderr); 112 }
二、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 128 8 #define READ 3 9 #define WRITE 5 10 void ErrorHandling(char *message); 11 unsigned int WINAPI EchoThreadMain(LPVOID pComPort); 12 13 typedef struct // socket info 14 { 15 SOCKET hClntSock; 16 SOCKADDR_IN clntAdr; 17 }PER_HANDLE_DATA, *LPPER_HANDLE_DATA; 18 19 typedef struct // buffer info 20 { 21 OVERLAPPED overlapped; 22 WSABUF wsaBuf; 23 char buffer[BUF_SIZE]; 24 int rwMode; // read or write 25 }PER_IO_DATA, *LPPER_IO_DATA; 26 27 int main(int argc, char *argv[]) 28 { 29 if (argc != 2) { 30 printf("Usage : %s <port> ", argv[0]); 31 exit(1); 32 } 33 34 WSADATA wsaData; 35 HANDLE hComPort; 36 SYSTEM_INFO sysInfo; 37 LPPER_IO_DATA ioInfo; 38 LPPER_HANDLE_DATA handleInfo; 39 40 SOCKET hServSock; 41 SOCKADDR_IN servAdr; 42 int recvBytes, i, flags = 0; 43 44 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 45 ErrorHandling("WSAStartup() error."); 46 47 hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); 48 GetSystemInfo(&sysInfo); 49 for (int i = 0; i < (int)sysInfo.dwNumberOfProcessors; i++) 50 _beginthreadex(NULL, 0, EchoThreadMain, (LPVOID)hComPort, 0, NULL); 51 52 hServSock = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 53 memset(&servAdr, 0, sizeof(servAdr)); 54 servAdr.sin_family = AF_INET; 55 servAdr.sin_addr.s_addr = htonl(INADDR_ANY); 56 servAdr.sin_port = htons(atoi(argv[1])); 57 58 bind(hServSock, (SOCKADDR*)&servAdr, sizeof(servAdr)); 59 listen(hServSock, 5); 60 61 puts("Server start..."); 62 while (1){ 63 SOCKET hClntSock; 64 SOCKADDR_IN clntAdr; 65 int addrLen = sizeof(clntAdr); 66 67 hClntSock = accept(hServSock, (SOCKADDR*)&clntAdr, &addrLen); 68 handleInfo = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA)); 69 handleInfo->hClntSock = hClntSock; 70 memcpy(&(handleInfo->clntAdr), &clntAdr, addrLen); 71 72 CreateIoCompletionPort((HANDLE)hClntSock, hComPort, (DWORD)handleInfo, 0); 73 74 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); 75 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 76 ioInfo->wsaBuf.len = BUF_SIZE; 77 ioInfo->wsaBuf.buf = ioInfo->buffer; 78 ioInfo->rwMode = READ; 79 WSARecv(handleInfo->hClntSock, &(ioInfo->wsaBuf), 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &(ioInfo->overlapped), NULL); 80 } 81 82 WSACleanup(); 83 return 0; 84 } 85 86 unsigned int WINAPI EchoThreadMain(LPVOID pComPort) 87 { 88 HANDLE hComPort = (HANDLE)pComPort; 89 SOCKET sock; 90 DWORD bytesTrans; 91 LPPER_HANDLE_DATA handleInfo; 92 LPPER_IO_DATA ioInfo; 93 DWORD flags = 0; 94 while (1) 95 { 96 GetQueuedCompletionStatus(hComPort, &bytesTrans, (LPDWORD)&handleInfo, (LPOVERLAPPED*)&ioInfo, INFINITE); 97 sock = handleInfo->hClntSock; 98 if (ioInfo->rwMode == READ) 99 { 100 puts("message received!"); 101 if (bytesTrans == 0) // 传输EOF 102 { 103 closesocket(sock); 104 free(handleInfo); 105 free(ioInfo); 106 continue; 107 } 108 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 109 ioInfo->wsaBuf.len = bytesTrans; 110 ioInfo->rwMode = WRITE; 111 WSASend(sock, &(ioInfo->wsaBuf), 1, NULL, 0, &(ioInfo->overlapped), NULL); 112 ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA)); 113 memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); 114 ioInfo->wsaBuf.len = BUF_SIZE; 115 ioInfo->wsaBuf.buf = ioInfo->buffer; 116 ioInfo->rwMode = READ; 117 WSARecv(sock, &(ioInfo->wsaBuf), 1, NULL, &flags, &(ioInfo->overlapped), NULL); 118 } 119 else{ 120 puts("message sent"); 121 free(ioInfo); 122 } 123 } 124 } 125 126 void ErrorHandling(char *message) { 127 fputs(message, stderr); 128 fputc(' ', stderr); 129 }