//////////////////////////////////////////////////
// WSAEventSelect文件#include "initsock.h"
#include <stdio.h>
#include <iostream.h>
#include <windows.h>// 初始化Winsock库
CInitSock theSock;int main()
{
// 事件句柄和套节字句柄表
WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS];
SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS];
int nEventTotal = 0; USHORT nPort = 4567; // 此服务器监听的端口号 // 创建监听套节字
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(nPort);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if(::bind(sListen, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf(" Failed bind() \n");
return -1;
}
::listen(sListen, 5); // 创建事件对象,并关联到新的套节字
WSAEVENT event = ::WSACreateEvent();
::WSAEventSelect(sListen, event, FD_ACCEPT|FD_CLOSE);
// 添加到表中
eventArray[nEventTotal] = event;
sockArray[nEventTotal] = sListen;
nEventTotal++; // 处理网络事件
while(TRUE)
{
// 在所有事件对象上等待
int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);
// 对每个事件调用WSAWaitForMultipleEvents函数,以便确定它的状态
nIndex = nIndex - WSA_WAIT_EVENT_0;
for(int i=nIndex; i<nEventTotal; i++)
{
nIndex = ::WSAWaitForMultipleEvents(1, &eventArray[i], TRUE, 1000, FALSE);
if(nIndex == WSA_WAIT_FAILED || nIndex == WSA_WAIT_TIMEOUT)
{
continue;
}
else
{
// 获取到来的通知消息,WSAEnumNetworkEvents函数会自动重置受信事件
WSANETWORKEVENTS event;
::WSAEnumNetworkEvents(sockArray[i], eventArray[i], &event);
if(event.lNetworkEvents & FD_ACCEPT) // 处理FD_ACCEPT通知消息
{
if(event.iErrorCode[FD_ACCEPT_BIT] == 0)
{
if(nEventTotal > WSA_MAXIMUM_WAIT_EVENTS)
{
printf(" Too many connections! \n");
continue;
}
SOCKET sNew = ::accept(sockArray[i], NULL, NULL);
WSAEVENT event = ::WSACreateEvent();
::WSAEventSelect(sNew, event, FD_READ|FD_CLOSE|FD_WRITE);
// 添加到表中
eventArray[nEventTotal] = event;
sockArray[nEventTotal] = sNew;
nEventTotal++;
}
}
else if(event.lNetworkEvents & FD_READ) // 处理FD_READ通知消息
{
if(event.iErrorCode[FD_READ_BIT] == 0)
{
char szText[256];
int nRecv = ::recv(sockArray[i], szText, strlen(szText), 0);
if(nRecv > 0)
{
szText[nRecv] = '\0';
printf("接收到数据:%s \n", szText);
}
}
}
else if(event.lNetworkEvents & FD_CLOSE) // 处理FD_CLOSE通知消息
{
if(event.iErrorCode[FD_CLOSE_BIT] == 0)
{
::closesocket(sockArray[i]);
for(int j=i; j<nEventTotal-1; j++)
{
sockArray[j] = sockArray[j+1];
sockArray[j] = sockArray[j+1];
}
nEventTotal--;
}
}
else if(event.lNetworkEvents & FD_WRITE) // 处理FD_WRITE通知消息
{
}
}
}
}
return 0;
}以上特殊颜色的是不懂的地方.
【1】第一个 [int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);]
中nIndex返回的是什么呀,是像FD_READ 这样的吗
【2】那为什么还要 [nIndex = nIndex - WSA_WAIT_EVENT_0;]呀,这是做什么的.为什么要减WSA_WAIT_EVENT_0
【3】减过之后为什么还要 [for(int i=nIndex; i<nEventTotal; i++)]循环,循环的时候为什么不是从i=0开始呀.而是从i=nIndex开始

解决方案 »

  1.   

    #include "initsock.h"
    中就包含了
    ::WSAStartup
    ::WSACleanup()
    所以不必考虑这些了
      

  2.   

    1、返回值是从WSA_WAIT_EVENT_0 到 (WSA_WAIT_EVENT_0 + cEvents - 1),表示WSAWaitForMultipleEvents()函数在等待的某一个事件已经触发
    2、nIndex = nIndex - WSA_WAIT_EVENT_0是因为获得的索引要去访问eventArray[WSA_MAXIMUM_WAIT_EVENTS]数组,当然得从0开始
    3、访问数组当然从0开始索引
      

  3.   

    这个是因为WSAWaitForMultipleEvents返回的时候有可能是多个event被signal了
    而返回的是第一个signaled的event的index,这个时候需要详细的检查之后的event。同时对这些signaled的event进行处理.........而nindex之前的event可以确定是没有singaled,可以不考虑............
      

  4.   

    那为什么要【nIndex = nIndex - WSA_WAIT_EVENT_0;】呢,
    为什么不直接[nIndex =nIndex +1]这样不就可以检查后面的是否也有事件发生吗【nIndex = nIndex - WSA_WAIT_EVENT_0;】代表什么,是什么意思呀.
    就这点不明白了
      

  5.   

    【1】第一个 [int nIndex = ::WSAWaitForMultipleEvents(nEventTotal, eventArray, FALSE, WSA_INFINITE, FALSE);] 
    中nIndex返回的是什么呀,是像FD_READ 这样的吗 
    如果等待成功,返回的是大于等于WSA_WAIT_EVENT_0的一个值,表示所等待的事件中哪一个触发了。【2】那为什么还要 [nIndex = nIndex - WSA_WAIT_EVENT_0;]呀,这是做什么的.为什么要减WSA_WAIT_EVENT_0 
    减去WSA_WAIT_EVENT_0,等到的就是触发的事件在eventArray数组中的下标。【3】减过之后为什么还要 [for(int i=nIndex; i <nEventTotal; i++)]循环,循环的时候为什么不是从i=0开始呀.而是从i=nIndex开始 
    从这开始循环,目的是检查还有哪些事件也触发了,因为WSAWaitForMultipleEvents的返回值是数组中第1个(按下标)触发的事件。
      

  6.   

    nIndex是表示eventArray中的第几个事件被等到,与FD-READ无关了,然后通过调用WSAEnumNetworkEvents获取具体的网络事件
    至于第2个nIndex = nIndex - WSA_WAIT_EVENT_0其实我觉得一般无关紧要的,因为通常都是从0开始的数组,更正确的说nIndex - WSA_WAIT_EVENT_0才是第几个事件被等到,也就是eventArray下标for(int i=nIndex; i <nEventTotal; i++)接着下面的事件等呀,总不能等到一个以后又从头开始吧,那后面总没机会了……