一、重叠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>\n", 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...\n");
 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('\n', stderr);
112 }
View Code

 

二、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>\n", 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('\n', stderr);
129 }
View Code

 

posted on 2019-04-02 23:56  acgame  阅读(140)  评论(0编辑  收藏  举报