这是我参与11月更文挑战的第二十四天,活动详情查看:2021最后一次更文挑战
事件选择模型
目的和要求
- 了解事件选择模型的应用场景;
- 掌握事件选择模型的通讯过程;
- 掌握事件选择模型的代码实现;
- 了解事件选择模型的改进方法:有序及增加客户端数量。
服务器端:
1、包含网络头文件网络库
1 | arduino复制代码#include <WinSock2.h> |
2、打开网络库
1 | arduino复制代码int nRes = WSAStartup(wdVersion, &wdScokMsg); |
3、校验版本
1 | scss复制代码if (2 != HIBYTE(wdScokMsg.wVersion) || 2 != LOBYTE(wdScokMsg.wVersion)) |
4、创建SOCKET
1 | ini复制代码SOCKET socketServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
5、绑定地址与端口
1 | scss复制代码if (SOCKET_ERROR == bind(socketServer, (const struct sockaddr*)&si, sizeof(si))) |
6、开始监听
1 | scss复制代码if (SOCKET_ERROR == listen(socketServer, SOMAXCONN)) |
7、事件选择模型
7.1定义fd_sockevent_set结构体
1 | ini复制代码WSAEVENT eventServer = WSACreateEvent(); |
7.2为服务器创建事件句柄
1 | scss复制代码if (WSAEventSelect(socketServer, eventServer, FD_ACCEPT) == SOCKET_ERROR) |
7.3为服务器SOCEKT和事件句柄绑定事件码:FD_ACCEPT,并放入
1 | ini复制代码sockevent_set |
7.4循环查询事件状态是否有信号,没有信号则重新查询
7.4.1使用WSAWaitForMultipleEvents查询有信号的事件对应socket句柄下标
1 | ini复制代码DWORD soindex = retSignal - WSA_WAIT_EVENT_0; |
7.4.2使用WSAEnumNetworkEvents获取事件操作码
7.4.3如果是FD_ACCEPT操作码
1 | scss复制代码if (NetworkEvents.lNetworkEvents & FD_ACCEPT) |
7.4.4如果是FD_WRITE操作码
1 | perl复制代码if (NetworkEvents.lNetworkEvents & FD_WRITE) |
7.4.5如果是FD_CLOSE操作码
1 | scss复制代码if (NetworkEvents.lNetworkEvents & FD_CLOSE) |
客户端
可以查看以前文章Select(TCP)模型
运行结果
事件选择模型相对于SELECT模型有什么不同?
Select(选择)模型是Winsock中最常见的I/O模型。之所以称其为“Select模型”,是由于它的“中心思想”便是利用select函数,实现对I/O的管理。最初设计该模型时,主要面向的是某些使用UNIX操作系统的计算机,它们采用的是Berkeley套接字方案。Select模型已集成到Winsock 1.1中,它使那些想避免在套接字调用过程中被无辜“锁定”的应用程序,采取一种有序的方式,同时进行对多个套接字的管理。由于Winsock 1.1向后兼容于Berkeley套接字实施方案,所以假如有一个Berkeley套接字应用使用了select函数,那么从理论角度讲,毋需对其进行任何修改,便可正常运行。
事件选择模型是Winsock提供的另一个有用的异步I/O模型。和WSAAsyncSelect模型类似的是,它也允许应用程序在一个或多个套接字上,接收以事件为基础的网络事件通知。由WSAAsyncSelect模型采用的网络事件来说,它们均可原封不动地移植到新模型。在用新模型开发的应用程序中,也能接收和处理所有那些事件。该模型最主要的差别在于网络事件会投递至一个事件对象句柄,而非投递至一个窗口例程。
本文转载自: 掘金