windows重叠I/O模型
Posted acgame
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了windows重叠I/O模型相关的知识,希望对你有一定的参考价值。
重叠I/O就相当于异步I/O。
一、重叠I/O的I/O完成确认
1、使用事件对象
接收端:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <WinSock2.h> 4 5 #define BUF_SIZE 1024 6 void ErrorHandling(char *message); 7 8 int main(int argc, char *argv[]) 9 { 10 if (argc != 2) { 11 printf("Usage : %s <port>\n", argv[0]); 12 exit(1); 13 } 14 15 WSADATA wsaData; 16 SOCKET hLinSock, hCRecvSock; 17 SOCKADDR_IN lisnAdr, recvAdr; 18 int recvAdrSz; 19 20 WSABUF dataBuf; 21 WSAEVENT evObj; 22 WSAOVERLAPPED overlapped; 23 24 char buf[BUF_SIZE]; 25 int recvBytes = 0, flags = 0; 26 27 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 28 ErrorHandling("WSAStartup() error."); 29 30 hLinSock = socket(PF_INET, SOCK_STREAM, 0); 31 memset(&lisnAdr, 0, sizeof(lisnAdr)); 32 lisnAdr.sin_family = AF_INET; 33 lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY); 34 lisnAdr.sin_port = htons(atoi(argv[1])); 35 36 if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR) 37 ErrorHandling("bind() error."); 38 if (listen(hLinSock, 5) == SOCKET_ERROR) 39 ErrorHandling("listen() error."); 40 41 recvAdrSz = sizeof(recvAdr); 42 hCRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz); 43 44 evObj = WSACreateEvent(); 45 memset(&overlapped, 0, sizeof(overlapped)); 46 overlapped.hEvent = evObj; 47 dataBuf.len = BUF_SIZE; 48 dataBuf.buf = buf; 49 50 if (WSARecv(hCRecvSock, &dataBuf, 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &overlapped, NULL) == SOCKET_ERROR) 51 { 52 if (WSAGetLastError() == WSA_IO_PENDING) 53 { 54 puts("Background data receive"); 55 WSAWaitForMultipleEvents(1, &evObj, TRUE, WSA_INFINITE, FALSE); 56 WSAGetOverlappedResult(hCRecvSock, &overlapped, (LPDWORD)&recvBytes, FALSE, NULL); 57 } 58 else{ 59 ErrorHandling("WSARECV() error"); 60 } 61 } 62 63 printf("Received message: %s\n", buf); 64 WSACloseEvent(evObj); 65 closesocket(hCRecvSock); 66 closesocket(hLinSock); 67 WSACleanup(); 68 return 0; 69 } 70 71 void ErrorHandling(char *message) { 72 fputs(message, stderr); 73 fputc(‘\n‘, stderr); 74 } 75 76 void CompressSockets(SOCKET hSockArr[], int idx, int total){ 77 for (int i = idx; i < total; i++) 78 hSockArr[i] = hSockArr[i + 1]; 79 } 80 81 void CompressEvents(WSAEVENT hEventArr[], int idx, int total){ 82 for (int i = idx; i < total; i++) 83 hEventArr[i] = hEventArr[i + 1]; 84 }
发送端:
1 #pragma warning(disable:4996) 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <winsock2.h> 6 7 void ErrorHandling(char *message); 8 9 int main(int argc, char* argv[]) { 10 if (argc != 3) { 11 printf("Usage : %s <IP> <port>\n", argv[0]); 12 exit(1); 13 } 14 15 WSADATA wsaData; 16 SOCKET hSocket; 17 SOCKADDR_IN sendAdr; 18 19 WSABUF dataBuf; 20 char msg[] = "Network is Computer!"; 21 int sendBytes = 0; 22 23 WSAEVENT evObj; 24 WSAOVERLAPPED overlapped; 25 26 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 27 ErrorHandling("WSAStartup() error"); 28 29 hSocket = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); 30 memset(&sendAdr, 0, sizeof(sendAdr)); 31 sendAdr.sin_family = AF_INET; 32 sendAdr.sin_addr.s_addr = inet_addr(argv[1]); 33 sendAdr.sin_port = htons(atoi(argv[2])); 34 35 if (connect(hSocket, (SOCKADDR*)&sendAdr, sizeof(sendAdr)) == SOCKET_ERROR) 36 ErrorHandling("connect() error"); 37 else 38 printf("Connected.......\n"); 39 40 evObj = WSACreateEvent(); 41 memset(&overlapped, 0, sizeof(overlapped)); 42 overlapped.hEvent = evObj; 43 dataBuf.len = strlen(msg) + 1; 44 dataBuf.buf = msg; 45 46 if (WSASend(hSocket, &dataBuf, 1, (LPDWORD)&sendBytes, 0, &overlapped, NULL) == SOCKET_ERROR){ 47 if (WSAGetLastError() == WSA_IO_PENDING){ 48 puts("Background data send"); 49 WSAWaitForMultipleEvents(1, &evObj, TRUE, WSA_INFINITE, FALSE); 50 WSAGetOverlappedResult(hSocket, &overlapped, (LPDWORD)&sendBytes, FALSE, NULL); 51 } 52 else{ 53 ErrorHandling("WSASend() error"); 54 } 55 } 56 printf("Send data size:%d\n", sendBytes); 57 WSACloseEvent(evObj); 58 closesocket(hSocket); 59 WSACleanup(); 60 return 0; 61 } 62 63 void ErrorHandling(char *message) { 64 fputs(message, stderr); 65 fputc(‘\n‘, stderr); 66 }
2、基于Completion Routine
接收端:
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 CompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); 8 9 WSABUF dataBuf; 10 char buf[BUF_SIZE]; 11 int recvBytes = 0; 12 13 int main(int argc, char *argv[]) 14 { 15 if (argc != 2) { 16 printf("Usage : %s <port>\n", argv[0]); 17 exit(1); 18 } 19 20 WSADATA wsaData; 21 SOCKET hLinSock, hRecvSock; 22 SOCKADDR_IN lisnAdr, recvAdr; 23 24 WSAEVENT evObj; 25 WSAOVERLAPPED overlapped; 26 27 int idx, recvAdrSz, flags = 0; 28 29 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 30 ErrorHandling("WSAStartup() error."); 31 32 hLinSock = socket(PF_INET, SOCK_STREAM, 0); 33 memset(&lisnAdr, 0, sizeof(lisnAdr)); 34 lisnAdr.sin_family = AF_INET; 35 lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY); 36 lisnAdr.sin_port = htons(atoi(argv[1])); 37 38 if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR) 39 ErrorHandling("bind() error."); 40 if (listen(hLinSock, 5) == SOCKET_ERROR) 41 ErrorHandling("listen() error."); 42 43 recvAdrSz = sizeof(recvAdr); 44 hRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz); 45 if (hRecvSock == INVALID_SOCKET) 46 ErrorHandling("accept() error"); 47 48 49 memset(&overlapped, 0, sizeof(overlapped)); 50 51 dataBuf.len = BUF_SIZE; 52 dataBuf.buf = buf; 53 54 evObj = WSACreateEvent(); 55 56 if (WSARecv(hRecvSock, &dataBuf, 1, (LPDWORD)&recvBytes, (LPDWORD)&flags, &overlapped, CompRoutine) == SOCKET_ERROR) 57 { 58 if (WSAGetLastError() == WSA_IO_PENDING) 59 { 60 puts("Background data receive"); 61 } 62 else{ 63 ErrorHandling("WSARECV() error"); 64 } 65 } 66 67 idx = WSAWaitForMultipleEvents(1, &evObj, FALSE, WSA_INFINITE, TRUE); 68 if (idx == WAIT_IO_COMPLETION) 69 puts("Overlapped I/O Completed"); 70 else 71 ErrorHandling("WSARecv() error"); 72 WSACloseEvent(evObj); 73 closesocket(hRecvSock); 74 closesocket(hLinSock); 75 WSACleanup(); 76 return 0; 77 } 78 79 void CALLBACK CompRoutine(DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags){ 80 81 if (dwError != 0){ 82 ErrorHandling("CompRoutine error"); 83 } 84 else{ 85 recvBytes = szRecvBytes; 86 printf("Received message: %s\n", buf); 87 } 88 } 89 90 void ErrorHandling(char *message) { 91 fputs(message, stderr); 92 fputc(‘\n‘, stderr); 93 }
发送端:同上
以上是关于windows重叠I/O模型的主要内容,如果未能解决你的问题,请参考以下文章