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 }
View Code

 

发送端:

技术图片
 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 }
View Code

 

 

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 }
View Code

 

发送端:同上

以上是关于windows重叠I/O模型的主要内容,如果未能解决你的问题,请参考以下文章

SOCKET重叠I/O模型

串行 I/O 与 Windows/Windows CE 重叠/非重叠

WinSock 异步I/O模型-3

win32网络模型之重叠I/O

Overlapped Model

检索具有多个重叠 I/O 请求的缓冲区