[00024]-[2015-09-19]-[02]-[WSAEventSelect 模型]

套接字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

[00024]-[2015-09-19]-[02]-[WSAEventSelect 模型]的相关文章

【我的书】Unity Shader的书 — 目录(2015.09.04更新)

写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shader的艰难,在群里也见了很多人提出的问题.我觉得学习Shader还是一件有规律可循的事情,但问题是中文资料难觅,而大家又不愿意去看英文...这对我有什么好处呢?强迫我对知识进行梳理,对细节问题把握更清楚. 第二个原因你懂的. 关于本书的定位问题: 面向Unity Shader初学者,但要: 有一定的

2015.09.30信息系统项目管理师作业

2015.09.30 高级 第八章 项目成本管理重点 1.成本管理的意义和范畴: 2.成本估算:是编制一个为完成项目各活动所需要的资源成本的估算:是一个要钱的计算:是申请资金的: 3.成本预算,是花钱的计划:成本预算的输出就是成本基线: 4.成本失控的原因:成本估算工作和成本预算工作不够准确细致,思想认识存在误区,项目在进行成本估算和预算没有统一规范, 5.成本估算内容对完成项目个项活动所必需的各种资源的成本做出近似的估算,:编制成本估算:编制成本造价:项目造价包括项目成本和项目盈利: 6.编制

winsock编程WSAEventSelect模型

winsock编程WSAEventSelect模型 WSAEventSelect模型和WSAAsyncSelec模型类似,都是用调用WSAXXXXXSelec函数将socket和事件关联并注册到系统,并将socket设置成非阻塞模式.二者不同之处在于socket事件的通知方法:WSAAsyncSelec模型利用窗口句柄和消息映射函数通知网络事件,而WSAEventSelect模型利用WSAEVENT通知网络事件.完成WSAEventSelect模型需要涉及以下函数或结构: 1:WSAEventS

我关注的一周技术动态 2015.09.13

服务化和资源管理技术 1. 「Allen 谈 Docker 系列」之 Docker 镜像内有啥,存哪? http://mp.weixin.qq.com/s?__biz=MzA5NTUxNzE4MQ==&mid=220597399&idx=1&sn=3196ab17d396df2379db61bc1f4e8652&scene=1&srcid=r3aAMluxx25ucjdz8AEA&key=dffc561732c226518710e3db4f30f5904c4

我关注的一周技术动态 2015.09.27

分布式系统实践 1. 走向分布式 http://dcaoyuan.github.io/papers/pdfs/Scalability.pdf 要点: 这是台湾的一个作者写的为期30天的分布式系统设计学习小册子, 刚开始涵盖了分布式系统设计的基本理论, 包括partiton, replication和CAP理论, 后面以kafka和zookeeper为例, 将上述理论加以实例化介绍, 内容非常精简, 适合初学者阅读和学习. 2. 如何编写一个分布式数据库 http://mp.weixin.qq.c

WSAEventSelect模型编程 详解

转自:http://blog.csdn.net/wangjieest/article/details/7042108 WSAEventSelect模型编程 WSAEventSelect模型编程这个模型是一个简单的异步事件模型,使用起来比较方便,现在说一下其的具体的用法和需要注意的地方.一,模型的例程(服务端):先举一个王艳平网络通信上的例子: [cpp] view plaincopyprint? //////////////////////////////////////////////////

WSAEventSelect模型详解

WSAEventSelect 是 WinSock 提供的一种异步事件通知I/O模型,与 WSAAsyncSelect模型有些类似.       该模型同样是接收 FD_XXX 之类的网络事件,但是是通过事件对象句柄通知,而非像 WSAAsyncSelect一样依靠Windows的消息驱动机制. 与WSAAsyncSelect模型相同,WSAEventSelect将所有的SOCKET事件分为如下类型:(共十种)                FD_READ , FD_WRITE , FD_OOB

【谜客帝国】第十一届阳光原创联想题会(2015.1.19)

谜客帝国第十一届阳光原创联想题会(2015.1.19)主持:阳光      计分:瓷1.取胜全靠兴奋剂 赤膊上阵遭败绩 屡败屡战是为何 拒绝吃药打点滴 3 不服输2.良月圆十分 坐山观虎斗 伤愈再请战 南非一地名 3 好望角3.感情深,一口闷  天初暖,日初长  苹叶软,杏花明  丛树深,万花芳 3 春光好[注:二面出自 唐  欧阳炯<春光好·天初暖>,三面出自 唐  和凝<春光好·苹叶软>,四面出自马彦<春光好.鼋头渚>]4.三言两语 乘法口诀 计座谈 言行一致  4

2015.09.13-2

常用js总结: function obj$(id)                       根据id得到对象function val$(id)                       根据id得到对象的值function trim(str)                      删除左边和右边空格function ltrim(str)                     删除左边空格function rtrim (str)                    删除右边空格fun