windows重叠I/O模型

时间:2023-12-24 15:52:19

重叠I/O就相当于异步I/O。

一、重叠I/O的I/O完成确认

1、使用事件对象

接收端:

 #include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message); int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET hLinSock, hCRecvSock;
SOCKADDR_IN lisnAdr, recvAdr;
int recvAdrSz; WSABUF dataBuf;
WSAEVENT evObj;
WSAOVERLAPPED overlapped; char buf[BUF_SIZE];
int recvBytes = , flags = ; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error."); hLinSock = socket(PF_INET, SOCK_STREAM, );
memset(&lisnAdr, , sizeof(lisnAdr));
lisnAdr.sin_family = AF_INET;
lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY);
lisnAdr.sin_port = htons(atoi(argv[])); if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error.");
if (listen(hLinSock, ) == SOCKET_ERROR)
ErrorHandling("listen() error."); recvAdrSz = sizeof(recvAdr);
hCRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz); evObj = WSACreateEvent();
memset(&overlapped, , sizeof(overlapped));
overlapped.hEvent = evObj;
dataBuf.len = BUF_SIZE;
dataBuf.buf = buf; if (WSARecv(hCRecvSock, &dataBuf, , (LPDWORD)&recvBytes, (LPDWORD)&flags, &overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSA_IO_PENDING)
{
puts("Background data receive");
WSAWaitForMultipleEvents(, &evObj, TRUE, WSA_INFINITE, FALSE);
WSAGetOverlappedResult(hCRecvSock, &overlapped, (LPDWORD)&recvBytes, FALSE, NULL);
}
else{
ErrorHandling("WSARECV() error");
}
} printf("Received message: %s\n", buf);
WSACloseEvent(evObj);
closesocket(hCRecvSock);
closesocket(hLinSock);
WSACleanup();
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
} void CompressSockets(SOCKET hSockArr[], int idx, int total){
for (int i = idx; i < total; i++)
hSockArr[i] = hSockArr[i + ];
} void CompressEvents(WSAEVENT hEventArr[], int idx, int total){
for (int i = idx; i < total; i++)
hEventArr[i] = hEventArr[i + ];
}

发送端:

 #pragma warning(disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h> void ErrorHandling(char *message); int main(int argc, char* argv[]) {
if (argc != ) {
printf("Usage : %s <IP> <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN sendAdr; WSABUF dataBuf;
char msg[] = "Network is Computer!";
int sendBytes = ; WSAEVENT evObj;
WSAOVERLAPPED overlapped; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error"); hSocket = WSASocket(PF_INET, SOCK_STREAM, , NULL, , WSA_FLAG_OVERLAPPED);
memset(&sendAdr, , sizeof(sendAdr));
sendAdr.sin_family = AF_INET;
sendAdr.sin_addr.s_addr = inet_addr(argv[]);
sendAdr.sin_port = htons(atoi(argv[])); if (connect(hSocket, (SOCKADDR*)&sendAdr, sizeof(sendAdr)) == SOCKET_ERROR)
ErrorHandling("connect() error");
else
printf("Connected.......\n"); evObj = WSACreateEvent();
memset(&overlapped, , sizeof(overlapped));
overlapped.hEvent = evObj;
dataBuf.len = strlen(msg) + ;
dataBuf.buf = msg; if (WSASend(hSocket, &dataBuf, , (LPDWORD)&sendBytes, , &overlapped, NULL) == SOCKET_ERROR){
if (WSAGetLastError() == WSA_IO_PENDING){
puts("Background data send");
WSAWaitForMultipleEvents(, &evObj, TRUE, WSA_INFINITE, FALSE);
WSAGetOverlappedResult(hSocket, &overlapped, (LPDWORD)&sendBytes, FALSE, NULL);
}
else{
ErrorHandling("WSASend() error");
}
}
printf("Send data size:%d\n", sendBytes);
WSACloseEvent(evObj);
closesocket(hSocket);
WSACleanup();
return ;
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}

2、基于Completion Routine

接收端:

 #include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h> #define BUF_SIZE 1024
void ErrorHandling(char *message);
void CALLBACK CompRoutine(DWORD, DWORD, LPWSAOVERLAPPED, DWORD); WSABUF dataBuf;
char buf[BUF_SIZE];
int recvBytes = ; int main(int argc, char *argv[])
{
if (argc != ) {
printf("Usage : %s <port>\n", argv[]);
exit();
} WSADATA wsaData;
SOCKET hLinSock, hRecvSock;
SOCKADDR_IN lisnAdr, recvAdr; WSAEVENT evObj;
WSAOVERLAPPED overlapped; int idx, recvAdrSz, flags = ; if (WSAStartup(MAKEWORD(, ), &wsaData) != )
ErrorHandling("WSAStartup() error."); hLinSock = socket(PF_INET, SOCK_STREAM, );
memset(&lisnAdr, , sizeof(lisnAdr));
lisnAdr.sin_family = AF_INET;
lisnAdr.sin_addr.s_addr = htonl(INADDR_ANY);
lisnAdr.sin_port = htons(atoi(argv[])); if (bind(hLinSock, (SOCKADDR*)&lisnAdr, sizeof(lisnAdr)) == SOCKET_ERROR)
ErrorHandling("bind() error.");
if (listen(hLinSock, ) == SOCKET_ERROR)
ErrorHandling("listen() error."); recvAdrSz = sizeof(recvAdr);
hRecvSock = accept(hLinSock, (SOCKADDR*)&recvAdr, &recvAdrSz);
if (hRecvSock == INVALID_SOCKET)
ErrorHandling("accept() error"); memset(&overlapped, , sizeof(overlapped)); dataBuf.len = BUF_SIZE;
dataBuf.buf = buf; evObj = WSACreateEvent(); if (WSARecv(hRecvSock, &dataBuf, , (LPDWORD)&recvBytes, (LPDWORD)&flags, &overlapped, CompRoutine) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSA_IO_PENDING)
{
puts("Background data receive");
}
else{
ErrorHandling("WSARECV() error");
}
} idx = WSAWaitForMultipleEvents(, &evObj, FALSE, WSA_INFINITE, TRUE);
if (idx == WAIT_IO_COMPLETION)
puts("Overlapped I/O Completed");
else
ErrorHandling("WSARecv() error");
WSACloseEvent(evObj);
closesocket(hRecvSock);
closesocket(hLinSock);
WSACleanup();
return ;
} void CALLBACK CompRoutine(DWORD dwError, DWORD szRecvBytes, LPWSAOVERLAPPED lpOverlapped, DWORD flags){ if (dwError != ){
ErrorHandling("CompRoutine error");
}
else{
recvBytes = szRecvBytes;
printf("Received message: %s\n", buf);
}
} void ErrorHandling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
}

发送端:同上