WSAWaitForMultipleEvents使用疑问

teleinfor 2010-10-12 12:03:04
下面的这个函数是一个WSAEventSelect模型的服务线程,多线程实现。这里作者使用了两个WSAWaitForMultipleEvents对事件对象数组进行检查网络事件。我怎么没看明白,是不是for()循环那个WSAWaitForMultipleEvents是不需要的?作者的用意是什么?给看看?

//处理I/O的线程
DWORD WINAPI ServerThread(LPVOID lpParam)
{
pTHREAD_OBJ pThread=(pTHREAD_OBJ)lpParam;
printf("新线程%d起动\n",GetCurrentThreadId());
while(true)
{
//等待网络事件
int nIndex=WSAWaitForMultipleEvents(pThread->nSocketCount+1,pThread->hEvents,false,WSA_INFINITE,false);
nIndex=nIndex-WSA_WAIT_EVENT_0;
//查看受信事件
for(int i=nIndex;i<pThread->nSocketCount+1;i++)
{
nIndex=WSAWaitForMultipleEvents(1,&pThread->hEvents[i],true,0,false);
if(WSA_WAIT_FAILED==nIndex||WSA_WAIT_TIMEOUT==nIndex)
{
continue;
}
else
{
if(0==i)
{
RebuildArray(pThread); // 重建句柄数组
if(pThread->nSocketCount==0)
{
FreeThreadObj(pThread);
printf("线程%d退出\n",GetCurrentThreadId());
return 0;
}
::WSAResetEvent(pThread->hEvents[0]);
}
else
{
pSOCKET_OBJ pSocket=FindSocketObj(pThread,i);
if(pSocket!=NULL)
{
if(!HandleIO(pThread,pSocket))
{
RebuildArray(pThread); // 重建句柄数组
}
}
else
{
printf("unable to find socket object\n");
}
}
}
}
}
}
...全文
1071 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
nokianasty 2013-02-21
  • 打赏
  • 举报
回复
mark .所言极是。
huangdi7922 2011-07-08
  • 打赏
  • 举报
回复
这是这样的,长时间不看又忘了啊
teleinfor 2010-10-12
  • 打赏
  • 举报
回复
多谢,总算明白了。的确如你所说,如果从业得不到机会,那么就会出现一直waiting的状态。这里还真的没有考虑过,看来多线程的同步处理的确有很多细节和应用场景有关系,笼统的了解和使用说不定什么时候就遇到以外的麻烦了。就想设计模式的单件模式遇到多线程情形也会有各种异常。

再次多谢。这个作者的考虑还是非常周全的。我起初就是不明白,但是总觉得他的设计自有其道理。
[Quote=引用 9 楼 stjay 的回复:]
引用 8 楼 teleinfor 的回复:
目的可能真的如你所说,但是我的理解是,即使多个event受信,这一轮只能处理一个,然后进入下一轮while循环,又可以等待到受信的event进行处理,这样的话就是通过while循环实现对个event句柄数组的监视了,这里作者添加了一个for循环遍历,是不是没有必要呢?其实多个for循环和利用一有的while循环从根本上来讲有否不同?有否影响逻辑的实现?……
[/Quote]
stjay 2010-10-12
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 teleinfor 的回复:]
目的可能真的如你所说,但是我的理解是,即使多个event受信,这一轮只能处理一个,然后进入下一轮while循环,又可以等待到受信的event进行处理,这样的话就是通过while循环实现对个event句柄数组的监视了,这里作者添加了一个for循环遍历,是不是没有必要呢?其实多个for循环和利用一有的while循环从根本上来讲有否不同?有否影响逻辑的实现?

引用 5 楼 visualeleven……
[/Quote]

如5楼所说
你可以百度一下WaitForMultipleObjects
其中有

多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。而WaitForMultipleObjects它只会改变使它返回的那个内核对象的状态。
这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将得不到被处理的机会。
为了解决这一问题,可以采用双WaitForMultipleObjects检测机制来实现。
teleinfor 2010-10-12
  • 打赏
  • 举报
回复
目的可能真的如你所说,但是我的理解是,即使多个event受信,这一轮只能处理一个,然后进入下一轮while循环,又可以等待到受信的event进行处理,这样的话就是通过while循环实现对个event句柄数组的监视了,这里作者添加了一个for循环遍历,是不是没有必要呢?其实多个for循环和利用一有的while循环从根本上来讲有否不同?有否影响逻辑的实现?
[Quote=引用 5 楼 visualeleven 的回复:]
第一个WSAWaitForMultipleEvents是等待事件对象Signal,如果同时有多个事件对象受信,WSAWaitForMultipleEvents函数的返回值也只能指明其中的一个,就事件句柄数组中最前面的那个。如果这个指明的事件对象总有网络事件发生,那么后面的其他事件对象所关联的网恋过事件就得不到及时的处理。因此WSAWaitForMultipleEvents函数返回以后,对每个事件对……
[/Quote]
ynwlgh 2010-10-12
  • 打赏
  • 举报
回复
我也是才刚起步学习...
头晕
guoxuqu 2010-10-12
  • 打赏
  • 举报
回复
没错,楼上正解。
Eleven 2010-10-12
  • 打赏
  • 举报
回复
第一个WSAWaitForMultipleEvents是等待事件对象Signal,如果同时有多个事件对象受信,WSAWaitForMultipleEvents函数的返回值也只能指明其中的一个,就事件句柄数组中最前面的那个。如果这个指明的事件对象总有网络事件发生,那么后面的其他事件对象所关联的网恋过事件就得不到及时的处理。因此WSAWaitForMultipleEvents函数返回以后,对每个事件对象再次调用WSAWaitForMultipleEvents函数,以确定其状态。
teleinfor 2010-10-12
  • 打赏
  • 举报
回复
是这个哥们的例子程序,一起看看?我个人觉得他这例子写的非常不错,结构清晰,代码规范,值得学习。
http://blog.csdn.net/heroyuchao/archive/2007/12/07/1922609.aspx
我就是没看懂他这里两次进行网络事件检测的设计。
[Quote=引用 3 楼 ynwlgh 的回复:]
可能它不是在等单一的事件.
这个前面的事件只是开始的信号.
后面的才是真正感兴趣的.
[/Quote]
ynwlgh 2010-10-12
  • 打赏
  • 举报
回复
可能它不是在等单一的事件.
这个前面的事件只是开始的信号.
后面的才是真正感兴趣的.
ynwlgh 2010-10-12
  • 打赏
  • 举报
回复
应该有是用的.
有什么用呢?
要看程序上下文.
这些个事件对象都是在哪个SOCKET里?
teleinfor 2010-10-12
  • 打赏
  • 举报
回复
我如果做如下的修改,不知道会修改原作者的意图么?

//处理I/O的线程
DWORD WINAPI ServerThread(LPVOID lpParam)
{
pTHREAD_OBJ pThread=(pTHREAD_OBJ)lpParam;
printf("新线程%d起动\n",GetCurrentThreadId());
while(true)
{
//等待网络事件
int nIndex=WSAWaitForMultipleEvents(pThread->nSocketCount+1,pThread->hEvents,false,WSA_INFINITE,false);
nIndex=nIndex-WSA_WAIT_EVENT_0;
if(WSA_WAIT_FAILED==nIndex||WSA_WAIT_TIMEOUT==nIndex)
{ // 失败或者超时
continue;
}
else
{ // 成功受信
if(0==nIndex) // pThread->hEvents[0]受信
{
RebuildArray(pThread); // 重建句柄数组
if(pThread->nSocketCount==0)
{
FreeThreadObj(pThread);
printf("线程%d退出\n",GetCurrentThreadId());
return 0;
}
::WSAResetEvent(pThread->hEvents[0]);
}
else
{
pSOCKET_OBJ pSocket=FindSocketObj(pThread,nIndex);
if(pSocket!=NULL)
{
if(!HandleIO(pThread,pSocket))
{
RebuildArray(pThread); // 重建句柄数组
}
}
else
{
printf("unable to find socket object\n");
}
}
}
}

//查看受信事件
// for(int i=nIndex;i<pThread->nSocketCount+1;i++)
// {
// nIndex=WSAWaitForMultipleEvents(1,&pThread->hEvents[i],true,0,false);
// if(WSA_WAIT_FAILED==nIndex||WSA_WAIT_TIMEOUT==nIndex)
// {
// continue;
// }
// else
// {
// if(0==i)
// {
// RebuildArray(pThread); // 重建句柄数组
// if(pThread->nSocketCount==0)
// {
// FreeThreadObj(pThread);
// printf("线程%d退出\n",GetCurrentThreadId());
// return 0;
// }
// ::WSAResetEvent(pThread->hEvents[0]);
// }
// else
// {
// pSOCKET_OBJ pSocket=FindSocketObj(pThread,i);
// if(pSocket!=NULL)
// {
// if(!HandleIO(pThread,pSocket))
// {
// RebuildArray(pThread); // 重建句柄数组
// }
// }
// else
// {
// printf("unable to find socket object\n");
// }
// }
// }
// }
//}
}

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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