一.io模型 :
异步选择模型 :像操作系统注册信息(socket,网络事件,消息),当指定网络事件发生时,接收消息
异步事件模型 :向操作系统注册信息(socket,网络事件,事件),当指定网络事件发生时,将事件置为有信号(最快)
二.异步事件类型的特点
1.被动通知
2.个数限制 64 (多线程 多个数组)
3.性能较优
存在问题
1.还是会阻塞:因为他需要自己从内存中拷贝信息
2.如果同时有两个事件发生信号,只会返回索引最小的那个,可能会造成数据丢失
三.流程简要
将创建好的套接字向windows注册,当相应套接字事件发生时,会返回网络信号,还有套接字在集合中的位置,根据相应位置的套接字和网络信号类型去处理。
四.简单的异步模型应用
该模型接收 FD_XXX 之类的网络事件,通过事件对象句柄通知,单线程实现一对多通信
网络事件是01串,可以通过相异注册多个网络事件
主要代码如下
//向windows注册,当有事件发生时会通知
HANDLE h_event = WSACreateEvent();//默认人工 无信号
//第一个参数是套接字,第二个是事件,第三个是网络信号类型
if (!WSAEventSelect(m_sock, h_event, FD_ACCEPT))//成功返回0,否则返回SOCKET_ERROR
{
m_arrevent[currentnum] = h_event;//将套接字和信号量绑定在一起
m_arraysock[currentnum] = m_sock;
currentnum++;
}
DWORD dwindex;//dwindex代表数组下标
WSANETWORKEVENTS we;
//哪个信号量到了,就干什么事
//等多个事件--有可能是fd_accept
dwindex = WSAWaitForMultipleEvents(pthis->currentnum,// 等待事件数量
pthis->m_arrevent,//等待事件的集合
FALSE, //1是全都等到返回,0是一个到就返回
FALSE, //等待时间
0);//返回值
dwindex -= WSA_WAIT_EVENT_0;//dwindew,返回最小索引值,减去WSA_WAIT_EVENT_0为下标
if (WSAEnumNetworkEvents(pthis->m_arraysock[dwindex],//事件的套接字
pthis->m_arrevent[dwindex],//哪一个事件
&we))//返回值一个 WSANETWORKEVENTS 类型指针
continue;
//信号为二进制数,不同位置的1代表不同的信号
if (we.lNetworkEvents & FD_ACCEPT)//看是否触发FD_ACCEPT信号,是则创建连接
{
//创建连接
SOCKET sockwinter = accept(pthis->m_sock, 0, 0);
if (sockwinter == INVALID_SOCKET)
continue;
//把创建的winter套接字向windows注册,信号为读取或者关闭
HANDLE event = WSACreateEvent();
if (!WSAEventSelect(sockwinter, event, FD_CLOSE | FD_READ))
{ //注册成功加入数组
pthis->m_arrevent[pthis->currentnum] = event;
pthis->m_arraysock[pthis->currentnum] = sockwinter;
pthis->currentnum++;
}
}
if (we.lNetworkEvents & FD_READ)//是可读信号
{
//接收数据
char buf[1024] = { 0 };
int nrecv = recv(pthis->m_arraysock[dwindex], buf, sizeof(buf), 0);
if (nrecv >= 0)
cout << buf << endl;
}
if (we.lNetworkEvents & FD_CLOSE)//断开连接信号
{
closesocket(pthis->m_arraysock[dwindex]);
WSACloseEvent(pthis->m_arrevent[dwindex]);
if (dwindex > 1)
{//将最后一个位置的,转移到删除的位置
pthis->m_arraysock[dwindex] = pthis->m_arraysock[pthis->currentnum - 1];
pthis->m_arrevent[dwindex] = pthis->m_arrevent[pthis->currentnum - 1];
}
pthis->currentnum--;//最后一个位置空出来
}