套接字WSAEventSelect模型
WSAEventSelect模型和WSAAsyncSelect模型相似,他们的区别是:
网络事件发生时系统通知应用程序的形式不同,WSAAsyncSelect模型以消息的形式通知应用程序,而WSAEventSelect模型以事件的形式通知应用程序;
WSAAsyncSelect模型和WSAEventSelect模型 相同点:
【一】这两个模型都是异步模型
【二】当网络事件发生时,应用程序都可以接受到网络通知
[WSAEventSelect]函数
int WSAEventSelect( SOCKET s, WSAEVENT hEventObject, Long lNetWorkEvens );
return 0 OR SOCKET_ERROR(调用WSAGetLastError()函数查看具体的错误代码)
FD_READ //有数据可读 FD_WRITE // 可以写数据 FD_ACCEPT // 接受连接 FD_CONNECT // 连接完成 FD_CLOSE // 套接字关闭 FD_OOB // 什么玩意儿 FD_QOS // 什么玩意儿 FD_GROUP_QOS // 什么玩意儿 FD_ROUTING_INTERFACE_CHANHE // 什么玩意儿 FD_ADDRESS_LIST_CHANGE // 什么玩意儿
[WSACreateEvent]函数
WSAEVENT WSACreateEvent(void); // 创建一个事件对象 创建一个以手动方式工作的事件对象,初始为无信号
[WSAResetEvent]函数
BOOL WSAResetEvent(WSAEVENT hEvent); // 设置事件对象为无信号
[WSACloseEvent]函数
BOOL WSACloseEvetn(WSAEVENT hEvent); // 释放事件对象占有的系统资源
[WSAWaitForMultipleEvents]函数
DWORD WSAWaitForMultipleEvents( DWORD cEvent, // 事件对象句柄数量 WSA_MAXIMUM_WAIT_EVENTS = 64 const WSAEVENT FAR* lphEvents, // 事件对象指针 BOOL fWaitAll, // 是否等待所有的事件对象都有“信号”才函数返回, ----> FALSE DWORD dwTimeOut, // 函数等待时间(阻塞) 0 ---》 立即返回 WSA_INFINITE ---》 无限等待 BOOL fAlertable // FALSE );
egcode:
#define WAIT_TIME 1000 // 等待1000ms SOCKET socketArray[WSA_MAXIMUM_WAIT_EVENTS]; WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS]; int nTotal = 0; DWORD dwIndex = WSAWaitForMultipleEvents(nTotal, eventArray, FALSE, WAIT_TIME, FALSE); WSAEVENT curEvent = eventArray[deIndex - WSA_WAIT_EVENT_0]; SOCKET curSocket = socketArray[deIndex - WSA_WAIT_EVENT_0];
[WSAEnumNetWorkEvent]函数
int WSAEnumNetWorkEvent( SOCKET s, WSAEVENT hEventObject, LPWSANETWORKEVENT lpNetworkEvents, ); typedef struct _WSANETWORKEVENTS{ long lNetworkEvents, // 发生的网络事件 int iErrorCode[FD_MAX_EVENTS] // 包含网络事件错误代码的数组 }WSANETWORKEVENTS, FAR *LPWSANETWORKEVENTS;
egproject:
// 构建CClient类
#define MAX_SIZE 1024 class CClient { public: CClient(SOCKET s){ m_s = s; } virtual ~CClient(); public: void RecData(void); void SendData(void); SOCKET GetSocket(void); void ProcessData(void); private: SOCKET m_s; char m_recvBuf[MAX_SIZE]; char m_sendBuf[MAX_SIZE]; }
// 创建客户端套接字管理的列表
typedef struct _socktnode { CClient* pClient; _socktnode* pNext; }SOCKETNODE, *PSOCKETNODE;
// 相关操作列表的API函数
PSOCKETNODE HeadNode = NULL; void AddNode(SOCKET s); // 添加节点 为什么以SOCKET s 为参数 在添加节点过程中 /* void AddNode(SOCKET s) { CClient* pClient = new CClient(s); // .... 添加该客户端拍Client return; } */ void DeleteNode(SOCKET s); // 删除节点 void DeleteAllNode(void); // 删除所有节点 清空列表 CClient* GetClient(SOCKET s); // 查找节点
// 定义相关变量
DWORD eventTotal = 0; WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS]; SOCKET socketArray[WSA_MAXIMUM_WAIT_EVENTS]; SOCKET sListen; // 监听套接字
//
WSAStartup(....); sListen = socket(AF_INET, .....); // sListen ===> socketArray[0] eventArray[eventTotal] = WSACreateEvent(); WSAEventSelect(sListen, eventArray[eventTotal], FD_ACCEPT|FD_CLOSE); bind(sListen, ....); listen(sListen, 5); eventTotal++;
//
while(m_bRunning) { dwIndex = WSAWaitForMultipleEvents(eventTotal, eventArray, FALSE, WSA_INFINITE, FALSE); WSANETWORKEVENTS networkEvents; WSAEnumNetworkEvents(socketArray[dwIndex - WSA_WAIT_EVENT_0], eventArray[dwIndex - WSA_WAIT_EVENT_0], &networkEvents ); if(networkEvents.lNetworkEvents & FD_ACCEPT) // 有客户端连接请求 { if(networkEvents.iErrorCode[FD_ACCEPT_BIT] != 0) // 检查是否发生网络错误 { // error handle } ::SendMessage(m_hMainDlg, WM_USER_ACCEPT, dweIndex, NULL); } if(networkEvents.lNetworkEvents & FD_READ) // 有客户端连接请求 { if(networkEvents.iErrorCode[FD_READ_BIT] != 0) // 检查是否发生网络错误 { // error handle } ::SendMessage(m_hMainDlg, WM_USER_READ, dweIndex, NULL); } if(networkEvents.lNetworkEvents & FD_CLOSE) // 有客户端连接请求 { if(networkEvents.iErrorCode[FD_CLOSE_BIT] != 0) // 检查是否发生网络错误 { // error handle } ::SendMessage(m_hMainDlg, WM_USER_CLOSE, dweIndex, NULL); } } #define WM_USER_ACCEPT WM_USER+100 #define WM_USER_READ WM_USER+101 #define WM_USER_CLOSE WM_USER+102 BEGIN_MESSAGE_MAP(CMainWnd, ....) ON_MESSAGE(WM_USER_ACCEPT, OnAccept) ON_MESSAGE(WM_USER_READ, OnRead) ON_MESSAGE(WM_USER_CLOSE, OnClose) END_MESSAGE_MAP() afx_msg LRESULT OnAccept(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnRead(WPARAM wParam, LPARAM lParam); afx_msg LRESULT OnClose(WPARAM wParam, LPARAM lParam); // 处理客户端连接请求 LRESULT OnAccept(WPARAM wParam, LPARAM lParam) { SOCKET sAccept; sAccpet = accept(m_arrSocekt[wParam - WSA_WAIT_EVENT_0], NULL, NULL); m_arrEvent[m_nEventTotal] = WSACreateEvent(void); m_arrSocket[m_nEventTotal] = sAccpet; AddNode(sAccpet); return 0; } // 处理数据接收消息 LRESULT OnRead(WPARAM wParam, LPARAM lParam) { CClient* pClient = GetClient(m_arrSocket[wParam - WSA_WAIT_EVENT_0]); pClient->RecData(); return 0; } // 处理套接字关闭消息 LRESULT OnClose(WPARAM wParam, LPARAM lParam) { return 0; }
时间: 2024-10-12 14:40:02