windows TCP/IP 网络编程(五)5种windows网络模型(4) 重叠IO模型(a)事件通知
1 重叠IO介绍
重叠IO两种反馈方式: ①事件通知 ②完成例程
2 重叠IO逻辑 和 性能
3 事件通知实现逻辑
4 创建socket
5 重叠IO
5.1 投递异步接收链接请求
5.2 WSARecv
5.3 WSASend
overlapped_event_server.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Winsock2.h>
#include <mswsock.h>
#include <string.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Mswsock.lib")
#define MAX_COUNT 1024
#define MAX_RECV_COUNT 1024
SOCKET all_socket[MAX_COUNT];
OVERLAPPED all_olp[MAX_COUNT];
int count = 0;
char recv_buf[MAX_RECV_COUNT];//接收缓冲区
void Clear()
{
for (int i = 0; i < count; i++)
{
closesocket(all_socket[i]);
WSACloseEvent(all_olp[i].hEvent);
}
}
BOOL WINAPI fun(DWORD dwCtrlType)
{
switch (dwCtrlType)
{
case CTRL_CLOSE_EVENT:
//释放所有socket
Clear();
break;
}
return TRUE;
}
int PostAccept();
int PostRecv(int index);
int PostSend(int index);
int main(int argc, char* argv[])
{
WORD wdVersion = MAKEWORD(2, 2);
WSADATA wdScokMsg;
int nRes = WSAStartup(wdVersion, &wdScokMsg);
if (0 != nRes)
{
switch (nRes)
{
case WSASYSNOTREADY:
printf("重启下电脑试试,或者检查网络库");
break;
case WSAVERNOTSUPPORTED:
printf("请更新网络库");
break;
case WSAEINPROGRESS:
printf("请重新启动");
break;
case WSAEPROCLIM:
printf("请尝试关掉不必要的软件,以为当前网络运行提供充足资源");
break;
}
return 0;
}
//校验版本
if (2 != HIBYTE(wdScokMsg.wVersion) || 2 != LOBYTE(wdScokMsg.wVersion))
{
//说明版本不对
//清理网络库
WSACleanup();
return 0;
}
SOCKET socketServer = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
//int a = WSAGetLastError();
if (INVALID_SOCKET == socketServer)
{
int a = WSAGetLastError();
//清理网络库
WSACleanup();
return 0;
}
struct sockaddr_in si;
si.sin_family = AF_INET;
si.sin_port = htons(12345);
si.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
//int a = ~0;
if (SOCKET_ERROR == bind(socketServer, (const struct sockaddr *)&si, sizeof(si)))
{
//出错了
int a = WSAGetLastError();
//释放
closesocket(socketServer);
//清理网络库
WSACleanup();
return 0;
}
if (SOCKET_ERROR == listen(socketServer, SOMAXCONN))
{
//出错了
int a = WSAGetLastError();
//释放
closesocket(socketServer);
//清理网络库
WSACleanup();
return 0;
}
all_socket[count] = socketServer;
all_olp[count].hEvent = WSACreateEvent();
count++;
if (0 != PostAccept())
{
Clear();
//清理网络库
WSACleanup();
return 0;
}
while (1)
{
for (int i = 0; i < count; i++)
{
int nRes = WSAWaitForMultipleEvents(1, &(all_olp[i].hEvent), FALSE, 0, FALSE);
if (WSA_WAIT_FAILED == nRes || WSA_WAIT_TIMEOUT == nRes)
{
continue;
}
//有信号了
DWORD state;
DWORD dw_flag;
BOOL b_flag = WSAGetOverlappedResult(all_socket[i], &all_olp[i], &state, TRUE, &dw_flag);
//信号置空
WSAResetEvent(all_olp[i].hEvent);
if (FALSE == b_flag)
{
int a = WSAGetLastError();
if (10054 == a)
{
printf("force close\n");
//客户端下线
//关闭
closesocket(all_socket[i]);
WSACloseEvent(all_olp[i].hEvent);
//从数组中删掉
all_socket[i] = all_socket[count - 1];
all_olp[i] = all_olp[count - 1];
//循环控制变量-1
i--;
//个数减-1
count--;
}
continue;
}
//成功
if (0 == i)
{
PostSend(count);
printf("accept\n");
//接收链接完成了
//投递recv
PostRecv(count);
//根据情况投递send
//客户端适量++
count++;
//投递accept
PostAccept();
continue;
}
if (0 == state)
{
printf("close\n");
//客户端下线
//关闭
closesocket(all_socket[i]);
WSACloseEvent(all_olp[i].hEvent);
//从数组中删掉
all_socket[i] = all_socket[count - 1];
all_olp[i] = all_olp[count - 1];
//循环控制变量-1
i--;
//个数减-1
count--;
continue;
}
if (0 != state)
{
//发送 或者 接收成功了
if (recv_buf[0] != 0)
{
//recv
//打印信息
printf("%s\n", recv_buf);
memset(recv_buf, 0, MAX_RECV_COUNT);
//根据情况投递send
//对自己投递接收
PostRecv(i);
}
else
{
//send
printf("发送完毕\n");
}
}
}
}
closesocket(socketServer);
//清理网络库
WSACleanup();
printf("\n");
system("pause");
return 0;
}
int PostAccept()
{
all_socket[count] = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
all_olp[count].hEvent = WSACreateEvent();
char str_buf[1024] = { 0 };
DWORD recv_cnt;
BOOL bRes = AcceptEx(all_socket[0], all_socket[count], str_buf, 0, sizeof(struct sockaddr_in) + 16,
sizeof(struct sockaddr_in) + 16, &recv_cnt, &all_olp[0]);
if (TRUE == bRes)
{
//立即完成了
//投递recv
PostRecv(count);
//根据情况投递send
//客户端适量++
count++;
//投递accept
PostAccept();
return 0;
}
else
{
int a = WSAGetLastError();
if (ERROR_IO_PENDING == a)
{
//延迟处理
return 0;
}
else
{
return a;
}
}
}
int PostRecv(int index)
{
WSABUF wsabuf;
wsabuf.buf = recv_buf;
wsabuf.len = 1024;
DWORD recv_count;
DWORD flag = 0;
int nRes = WSARecv(all_socket[index], &wsabuf, 1, &recv_count, &flag, &all_olp[index], NULL);
if (0 == nRes)
{
//立即完成的
//打印信息
printf("%s\n", wsabuf.buf);
memset(recv_buf, 0, MAX_RECV_COUNT);
//根据情况投递send
//对自己投递接收
PostRecv(index);
return 0;
}
else
{
int a = WSAGetLastError();
if (ERROR_IO_PENDING == a)
{
//延迟处理
return 0;
}
else
{
return a;
}
}
}
int PostSend(int index)
{
WSABUF wsabuf;
wsabuf.buf = "你好";
wsabuf.len = MAX_RECV_COUNT;
DWORD send_count;
DWORD flag = 0;
int nRes = WSASend(all_socket[index], &wsabuf, 1, &send_count, flag, &all_olp[index], NULL);
if (0 == nRes)
{
//立即完成的
//打印信息
printf("send成功\n");
return 0;
}
else
{
int a = WSAGetLastError();
if (ERROR_IO_PENDING == a)
{
//延迟处理
return 0;
}
else
{
return a;
}
}
}