关于WSAWaitForMultipleEvents

sunshinee 2004-08-19 10:35:25
根据网络编程中几种I/O模式的比较,WSAEventSelect在体现并发连接上体现了很好的性能。
可是WSAWaitForMultipleEvents一次最多只能等待64个连接,如果需要等待更多的连接,需要用到多线程,可是不知道这个多线程怎么构建和同步,请大家一起讨论!
...全文
189 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
dxh2002 2004-10-26
  • 打赏
  • 举报
回复
楼上的给我发一份吧

duxiaohu2002@163.com
DentistryDoctor 2004-09-02
  • 打赏
  • 举报
回复
《Windows核心编程》的源码你有么?没有发一份给你,给我留言。
DentistryDoctor 2004-09-02
  • 打赏
  • 举报
回复
/******************************************************************************
Module: WaitForMultExp.cpp
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/


#include "..\CmnHdr.h" /* See Appendix A. */
#include <malloc.h>
#include <process.h>
#include "WaitForMultExp.h"


///////////////////////////////////////////////////////////////////////////////


// Internal data structure representing a single expression.
// Used to tell OR-threads what objects to wait on.
typedef struct {
PHANDLE m_phExpObjects; // Points to set of handles
DWORD m_nExpObjects; // Number of handles
} EXPRESSION, *PEXPRESSION;


///////////////////////////////////////////////////////////////////////////////


// The OR-thread function
DWORD WINAPI WFME_ThreadExpression(PVOID pvParam) {

// This thread function just waits for an expression to come true.
// The thread waits in an alertable state so that it can be forced
// to stop waiting by queuing an entry to its APC queue.
PEXPRESSION pExpression = (PEXPRESSION) pvParam;
return(WaitForMultipleObjectsEx(
pExpression->m_nExpObjects, pExpression->m_phExpObjects,
TRUE, INFINITE, TRUE));
}


///////////////////////////////////////////////////////////////////////////////


// This is the APC callback routine function
VOID WINAPI WFME_ExpressionAPC(ULONG_PTR dwData) {

// This function intentionally left blank
}


///////////////////////////////////////////////////////////////////////////////


// Function to wait on mutiple Boolean expressions
DWORD WINAPI WaitForMultipleExpressions(DWORD nExpObjects,
CONST HANDLE* phExpObjects, DWORD dwMilliseconds) {

// Allocate a temporary array because we modify the passed array and
// we need to add a handle at the end for the hsemOnlyOne semaphore.
PHANDLE phExpObjectsTemp = (PHANDLE)
_alloca(sizeof(HANDLE) * (nExpObjects + 1));
CopyMemory(phExpObjectsTemp, phExpObjects, sizeof(HANDLE) * nExpObjects);
phExpObjectsTemp[nExpObjects] = NULL; // Put sentinel at end

// Semaphore to guarantee that only one expression gets satisfied
HANDLE hsemOnlyOne = CreateSemaphore(NULL, 1, 1, NULL);

// Expression information: 1 per possible thread
EXPRESSION Expression[MAXIMUM_WAIT_OBJECTS];

DWORD dwExpNum = 0; // Current expression number
DWORD dwNumExps = 0; // Total number of expressions

DWORD dwObjBegin = 0; // First index of a set
DWORD dwObjCur = 0; // Current index of object in a set

DWORD dwThreadId, dwWaitRet = 0;

// Array of thread handles for threads: 1 per expression
HANDLE ahThreads[MAXIMUM_WAIT_OBJECTS];

// Parse the callers handle list by initializing a structure for
// each expression and adding hsemOnlyOne to each expression.
while ((dwWaitRet != WAIT_FAILED) && (dwObjCur <= nExpObjects)) {

// While no errors, and object handles are in the caller's list...

// Find next expression (OR-expressions are separated by NULL handles)
while (phExpObjectsTemp[dwObjCur] != NULL)
dwObjCur++;

// Initialize Expression structure which an OR-thread waits on
phExpObjectsTemp[dwObjCur] = hsemOnlyOne;
Expression[dwNumExps].m_phExpObjects = &phExpObjectsTemp[dwObjBegin];
Expression[dwNumExps].m_nExpObjects = dwObjCur - dwObjBegin + 1;

if (Expression[dwNumExps].m_nExpObjects > MAXIMUM_WAIT_OBJECTS) {
// Error: Too many handles in single expression
dwWaitRet = WAIT_FAILED;
SetLastError(ERROR_SECRET_TOO_LONG);
}

// Advance to the next expression
dwObjBegin = ++dwObjCur;
if (++dwNumExps == MAXIMUM_WAIT_OBJECTS) {
// Error: Too many expressions
dwWaitRet = WAIT_FAILED;
SetLastError(ERROR_TOO_MANY_SECRETS);
}
}

if (dwWaitRet != WAIT_FAILED) {

// No errors occurred while parsing the handle list

// Spawn thread to wait on each expression
for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {

ahThreads[dwExpNum] = chBEGINTHREADEX(NULL,
1, // We only require a small stack
WFME_ThreadExpression, &Expression[dwExpNum],
0, &dwThreadId);
}

// Wait for an expression to come TRUE or for a timeout
dwWaitRet = WaitForMultipleObjects(dwExpNum, ahThreads,
FALSE, dwMilliseconds);

if (WAIT_TIMEOUT == dwWaitRet) {

// We timed-out, check if any expressions were satisfied by
// checking the state of the hsemOnlyOne semaphore.
dwWaitRet = WaitForSingleObject(hsemOnlyOne, 0);

if (WAIT_TIMEOUT == dwWaitRet) {

// If the semaphore was not signaled, some thread expressions
// was satisfied; we need to determine which expression.
dwWaitRet = WaitForMultipleObjects(dwExpNum,
ahThreads, FALSE, INFINITE);

} else {

// No expression was satisfied and WaitForSingleObject just gave
// us the semaphore so we know that no expression can ever be
// satisfied now -- waiting for an expression has timed-out.
dwWaitRet = WAIT_TIMEOUT;
}
}

// Break all the waiting expression threads out of their
// wait state so that they can terminate cleanly.
for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {

if ((WAIT_TIMEOUT == dwWaitRet) ||
(dwExpNum != (dwWaitRet - WAIT_OBJECT_0))) {

QueueUserAPC(WFME_ExpressionAPC, ahThreads[dwExpNum], 0);
}
}

#ifdef _DEBUG
// In debug builds, wait for all of expression threads to terminate
// to make sure that we are forcing the threads to wake up.
// In non-debug builds, we'll assume that this works and
// not keep this thread waiting any longer.
WaitForMultipleObjects(dwExpNum, ahThreads, TRUE, INFINITE);
#endif

// Close our handles to all the expression threads
for (dwExpNum = 0; dwExpNum < dwNumExps; dwExpNum++) {
CloseHandle(ahThreads[dwExpNum]);
}
} // error occurred while parsing

CloseHandle(hsemOnlyOne);
return(dwWaitRet);
}


//////////////////////////////// End of File //////////////////////////////////
DentistryDoctor 2004-09-02
  • 打赏
  • 举报
回复
/******************************************************************************
Module: WaitForMultExp.h
Notices: Copyright (c) 2000 Jeffrey Richter
******************************************************************************/


#pragma once


///////////////////////////////////////////////////////////////////////////////


DWORD WINAPI WaitForMultipleExpressions(DWORD nExpObjects,
CONST HANDLE* phExpObjects, DWORD dwMilliseconds);


//////////////////////////////// End of File //////////////////////////////////
DentistryDoctor 2004-08-19
  • 打赏
  • 举报
回复
WaitForMultEx,你看了么?
sunshinee 2004-08-19
  • 打赏
  • 举报
回复
个人觉得重叠模型和完成端口都太大了,而且,在处理并发连接方面,WSAEventSelect也表现得很不错的!
msdn_user 2004-08-19
  • 打赏
  • 举报
回复
可以采用别的模型
比如重叠模型和完成端口模型
DentistryDoctor 2004-08-19
  • 打赏
  • 举报
回复
《Windows核心编程》第十章有一例子,WaitForMultEx就是讲这个的。
其实线程比较多的时可以采用线程池。
sunshinee 2004-08-19
  • 打赏
  • 举报
回复
楼上的,有吗?我怎么没有找到啊!
DentistryDoctor 2004-08-19
  • 打赏
  • 举报
回复
明天将WaitForMultEx的代码给你贴出来,我得GO HOME了。
lianglp 2004-08-19
  • 打赏
  • 举报
回复
至于同步,可以设置一个临界区,当对这个链表操作的时候,都设置临界区。
lianglp 2004-08-19
  • 打赏
  • 举报
回复
如果楼主非要用WSAEventSelect模型来进行网络数据等事件的触发,服务器端
可以创建一个数据结构,大概情况如下:
struct
{
DWORD dwThreadId ;//这个表示sk是属于那个线程进行等待
WSAEVENT hEvent ;//与sk相关联的事件句柄
SOCKET sk ;//产生的套接字
}
把这个数据结构保存到链表中,
这样每当产生一个新的服务器会话句柄,可以先以线程ID为关键字检查链表中的
每个线程中已有多少个事件,如果超过(目前最大不能超过64个,受WSAWaitForMultipleEvents()限制),则再开一个线程。
sunshinee 2004-08-19
  • 打赏
  • 举报
回复
自己顶一把。
希望大家一起来讨论一下~
有时觉得并非什么都要用I/O重叠和完成端口来做,如果其他的几种I/O模式可以达到要求那为什么要舍易求难呢!
sunshinee 2004-08-19
  • 打赏
  • 举报
回复
这个是扩展,倒没有看过。
不过只是觉得WSAEventSelect可以满足我的需求了,为什么不直接用这个呢?
因为我要求就是要并发连接,在这方面WSAEventSelect有不俗的表现啊!
关键现在是不知道该怎么构建这些多线程!

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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