WSAWaitForMultipleEvents 没有for循环了,是怎么回事?

bsnry 2014-09-23 12:41:05
PiggyXP 的博客里的代码, 讲解overlapped io的用法。

链接:
http://download.csdn.net/detail/PiggyXP/277751

部分代码为:

// 重叠I/O处理线程
UINT _OverlappedThread(LPVOID lParam)
{
CServerSocket* pServer = (CServerSocket*)lParam;

while(bOverlapped) // 循环检测事件数组中的事件,并对接收的数据进行处理:)
{
DWORD dwIndex;

// 等候重叠I/O调用结束
// 因为我们把事件和Overlapped绑定在一起,重叠操作完成后我们会接到事件通知
dwIndex = WSAWaitForMultipleEvents(dwEventTotal,EventArray,FALSE,10,FALSE);

if(dwIndex == WSA_WAIT_TIMEOUT)
continue;

if(dwIndex == WSA_WAIT_FAILED) // 出现监听错误
{
int nErrorCode = WSAGetLastError();

if(nErrorCode == WSA_INVALID_HANDLE)
{
AfxMessageBox("监听出现错误:无效的 lphEvents 参数!"); // 代码经常会出现这种错误,我实在没时间改了,55555555
}
else
if(nErrorCode == WSA_INVALID_PARAMETER)
{
AfxMessageBox("监听出现错误:无效的 CEvents 参数!");
}

continue;
}

// 取得索引值,得知事件的索引号
dwIndex = dwIndex - WSA_WAIT_EVENT_0;

// 获得索引号以后,这个事件已经没有利用价值,重置之
WSAResetEvent(EventArray[dwIndex]);

// 然后确定当前索引号的SOCKET的重叠请求状态
DWORD dwBytesTransferred;
WSAOVERLAPPED& CurrentOverlapped = AcceptOverlapped[dwIndex]; // 这里纯粹为了减少代码长度,付给了一个临时变量
SOCKET& sockCurrent = sockAcceptArray[dwIndex] ; // 同上

WSAGetOverlappedResult(sockCurrent,¤tOverlapped ,
&dwBytesTransferred,FALSE,&Flags);

// 先检查通信对方是否已经关闭连接
// 如果==0则表示连接已经,则关闭套接字
if(dwBytesTransferred == 0)
{
CString strSock;
strSock.Format("SOCKET编号:%d",sockAcceptArray[dwIndex] );
::SendMessage(pServer->m_hNotifyWnd,WM_MSG_NEW_SOCKET,
(LPARAM)(LPCTSTR)strSock,(LPARAM)(LPCTSTR)"客户端断开连接!");

closesocket(sockCurrent);
sockCurrent = INVALID_SOCKET;
//WSACloseEvent( EventArray[dwIndex] );

dwEventTotal--;
if(dwEventTotal <= 0) // 如果没有事件等待则暂停重叠IO处理线程
{

pOverlappedThread->SuspendThread(); // 没有需要处理的重叠结构了,则本线程休眠
}
continue;
}


// DataBuf中包含接收到的数据,我们发到对话框中给予显示
CString strSock;
strSock.Format("SOCKET编号:%d",sockCurrent);
::SendMessage(pServer->m_hNotifyWnd,WM_MSG_NEW_MSG,
(LPARAM)(LPCTSTR)strSock,(LPARAM)(LPCTSTR)DataBuf[dwIndex].buf);


// 然后在套接字上投递另一个WSARecv请求(不要晕,注意看,代码和前面第一次WSARecv一样^_^)
Flags = 0;
ZeroMemory(¤tOverlapped,sizeof(WSAOVERLAPPED));

char buffer[DATA_BUFSIZE];
ZeroMemory(buffer,DATA_BUFSIZE);

CurrentOverlapped.hEvent = EventArray[dwIndex];
DataBuf[dwIndex].len = DATA_BUFSIZE;
DataBuf[dwIndex].buf = buffer;

// 开始另外一个WSARecv
if(WSARecv(sockCurrent,&DataBuf[dwIndex],1,&dwRecvBytes,&Flags,
¤tOverlapped ,NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
AfxMessageBox("错误:投递Recv操作失败!!此套接字将被关闭!");

closesocket(sockCurrent);
sockCurrent = INVALID_SOCKET;

WSACloseEvent(EventArray[dwIndex]);

dwEventTotal--;

continue;
}
}
}

return 0;
}


代码里只有一个wsawaitformutipleevents, 一般都有2个。

为什么只有一个。

...全文
146 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
阿呆_ 2014-09-25
  • 打赏
  • 举报
回复
没什么可神奇的。手动event signal后必须手动reset否则一直保持signal状态。WaitForMultipleEvents/WSAWaitForMultipleEvents如果不要求全部events都signal才返回的话,如果等待的event中有任何一个是signal状态的话它当然是立即返回啦。 因此如果一次等待中有多个events都signal了,你处理时只reset了一个,那么下次wait时必然立即返回上一次signal中的另一个。
阿呆_ 2014-09-24
  • 打赏
  • 举报
回复
从代码中WSAResetEvent(EventArray[dwIndex]);可以看出,它waitfor的都是手动reset的event,因此如果有多个event同时signal的话,处理完一个待循环又一次进入WSAWaitForMultipleEvents时会立即返回下一个signal的event。所以没有必要多次WaitFor (很明显代码对waitfor的顺序没有要求,哪怕同一个event signal多次造成另一个event的signal不能及时处理也是设计的一部分)。
bsnry 2014-09-24
  • 打赏
  • 举报
回复
引用 6 楼 Idle_ 的回复:
从代码中WSAResetEvent(EventArray[dwIndex]);可以看出,它waitfor的都是手动reset的event,因此如果有多个event同时signal的话,处理完一个待循环又一次进入WSAWaitForMultipleEvents时会立即返回下一个signal的event。所以没有必要多次WaitFor (很明显代码对waitfor的顺序没有要求,哪怕同一个event signal多次造成另一个event的signal不能及时处理也是设计的一部分)。
它waitfor的都是手动reset的event,因此如果有多个event同时signal的话,处理完一个待循环又一次进入WSAWaitForMultipleEvents时会立即返回下一个event 有点神奇了
bsnry 2014-09-23
  • 打赏
  • 举报
回复
引用 4 楼 Idle_ 的回复:
[quote=引用 3 楼 SiGoYi 的回复:] [quote=引用 2 楼 Idle_ 的回复:] [quote=引用 1 楼 bsnry 的回复:] 代码是个bug, 不知道为什么没人发现?
真没看出来哪里有bug。 另:谁规定必须有两个wsawaitformutipleevents的?[/quote] wsawaitformutipleevents中几个event都可以,是根据你设置的前两个参数定的,一个是handle数组,另一个是数组的count。[/quote] ??? 为什么引用我的话? 而且好像说的和我说的没关系吧?[/quote]
引用 3 楼 SiGoYi 的回复:
[quote=引用 2 楼 Idle_ 的回复:] [quote=引用 1 楼 bsnry 的回复:] 代码是个bug, 不知道为什么没人发现?
真没看出来哪里有bug。 另:谁规定必须有两个wsawaitformutipleevents的?[/quote] wsawaitformutipleevents中几个event都可以,是根据你设置的前两个参数定的,一个是handle数组,另一个是数组的count。[/quote] 使用2个的原因: 防止 有的event 处于饥饿状态。wsawaitformutipleevents 这个api是 一系列事件(事件数组)中有一个事件有信号,就返回。 且返回最小索引。 所以,一般的demo里,都会使用2个, 第一个检测 是否有信号。 第2个来确定,到底是谁有信号。 所以会出现一个for(int i = nindex ; nindex < 事件总数; i++) 这样的代码。
阿呆_ 2014-09-23
  • 打赏
  • 举报
回复
引用 3 楼 SiGoYi 的回复:
[quote=引用 2 楼 Idle_ 的回复:] [quote=引用 1 楼 bsnry 的回复:] 代码是个bug, 不知道为什么没人发现?
真没看出来哪里有bug。 另:谁规定必须有两个wsawaitformutipleevents的?[/quote] wsawaitformutipleevents中几个event都可以,是根据你设置的前两个参数定的,一个是handle数组,另一个是数组的count。[/quote] ??? 为什么引用我的话? 而且好像说的和我说的没关系吧?
SiGoYi 2014-09-23
  • 打赏
  • 举报
回复
引用 2 楼 Idle_ 的回复:
[quote=引用 1 楼 bsnry 的回复:] 代码是个bug, 不知道为什么没人发现?
真没看出来哪里有bug。 另:谁规定必须有两个wsawaitformutipleevents的?[/quote] wsawaitformutipleevents中几个event都可以,是根据你设置的前两个参数定的,一个是handle数组,另一个是数组的count。
阿呆_ 2014-09-23
  • 打赏
  • 举报
回复
引用 1 楼 bsnry 的回复:
代码是个bug, 不知道为什么没人发现?
真没看出来哪里有bug。 另:谁规定必须有两个wsawaitformutipleevents的?
bsnry 2014-09-23
  • 打赏
  • 举报
回复
代码是个bug, 不知道为什么没人发现?

16,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧