下面是CMultipleHandles和一个基于Console的源码。
// MultipleHandles.h
// 作者: 黄瑞广 时间: 2004-02-06
// 说明: 本类不支持线程安全
class CMultipleHandles
{
private:
int m_nNumOfHandle;
public:
HANDLE m_arrayHandle[MAXIMUM_WAIT_OBJECTS];
...........
};
// MultipleHandles.cpp
#include "stdafx.h"
#include "MultipleHandles.h"
CMultipleHandles::CMultipleHandles()
{
Init();
}
void CMultipleHandles::Init()
{
m_nNumOfHandle = 0; // 句柄数为"0"
for (int i = 0; i < MAXIMUM_WAIT_OBJECTS; i++)
m_arrayHandle[i] = NULL; // NULL表示该句柄位可用
}
// 功能: 判断句柄槽位是否是空
// 返回值: TRUE, 空; FALSE, 不空
BOOL CMultipleHandles::IsEmpty()
{
if (m_nNumOfHandle == 0)
return TRUE;
return FALSE;
}
// 功能: 判断句柄槽位是否已满
// 返回值: TRUE, 已满; FALSE, 未满
BOOL CMultipleHandles::IsFull()
{
if (m_nNumOfHandle == MAXIMUM_WAIT_OBJECTS)
return TRUE;
return FALSE;
}
// 功能: 获得可用槽位的索引值
// 返回值: -1, 没有可用的槽位; 否则是空槽位的索引
int CMultipleHandles::GetFree()
{
int nIndex;
if (IsFull())
return -1; // 整个句柄槽没有可用的槽位, 返回-1
for (int i = 0; i < MAXIMUM_WAIT_OBJECTS; i++)
{
if (m_arrayHandle[i] == NULL)
{
nIndex = i;
break;
}
}
return nIndex;
}
// 功能: 获得句柄槽中句柄的个数
// 返回值: 句柄个数
int CMultipleHandles::GetNumOfHandle()
{
return m_nNumOfHandle;
}
// 功能: 把一个句柄插入到句柄槽中
// 参数: 句柄, 作为输入
// 返回值: -1, 线程槽已满,插入失败; 成功, 返回插入索引值
int CMultipleHandles::Insert(const HANDLE hParam)
{
int nIndex;
nIndex = GetFree();
if (nIndex == -1)
return -1;
m_arrayHandle[nIndex] = hParam;
m_nNumOfHandle++;
return nIndex;
}
// 功能: 清除句柄槽中指定的句柄
// 参数: 输入, 句柄索引
// 返回值: TRUE, 成功; FALSE, 失败
BOOL CMultipleHandles::Clear(int nIndex)
{
if (IsEmpty())
return FALSE;
m_arrayHandle[nIndex] = NULL;
m_nNumOfHandle--;
return TRUE;
}
// 功能: 重置线程槽的槽位
// 返回值: TRUE, 重置成功; FALSE, 失败
BOOL CMultipleHandles::Reset()
{
if (m_nNumOfHandle == 0) // 句柄槽中已没有可用句柄
return FALSE;
HANDLE arrayTempHandle[MAXIMUM_WAIT_OBJECTS];
// 在句柄槽中未清除句柄前的句柄个数是m_nNumOfHandle + 1
// 把须要重置的句柄索引的上限定为m_nNumOfHandle是为了提高程序的效率,
// 因为在大多数情况下, 须重置的句柄个数会<<MAXIMUM_WAIT_OBJECTS(64).
for (int i = 0, j = 0; i < m_nNumOfHandle + 1; i++)
{
if (m_arrayHandle[i] == NULL)
continue;
// 将句柄槽中的句柄复制到一个监时数据组中
arrayTempHandle[j] = m_arrayHandle[i];
j++;
}
// 将原来的数组空间初始化
for (i = 0; i < m_nNumOfHandle + 1; i++)
m_arrayHandle[i] = NULL;
// 将临时数组的数据拷贝
for (i = 0; i < m_nNumOfHandle; i++)
m_arrayHandle[i] = arrayTempHandle[i];
return TRUE;
}
上面这类在效率上不高需要改进。
// Console 主函数
int main()
{
BOOL bIsFrist = FALSE;
// Start winsock and create listen socket
nRet = listen(listensock, 5);
CMultipleHandles multipleHandles; // 声明线程槽对
while (TRUE)
{
if (!bIsFrist) // 不是第一次执行循环
{
for (;;)
{
if (multipleHandles.IsEmpty()) // 线程句柄槽是空的, 不循环
break;
nRet = WaitForMultipleObjects(
multipleHandles.GetNumOfHandle(),
multipleHandles.m_arrayHandle,
FALSE, // 有一个事件处于激发态, 函数就返回
0 // 函数检查所有事件的状态后, 立即返回
);
if (nRet == WAIT_FAILED | nRet == WAIT_TIMEOUT)
break;
else
{
// 关闭线程槽的某个槽位中已处于激发状态的线程句柄 CloseHandle(multipleHandles.m_arrayHandle[nRet - WAIT_OBJECT_0]);
// 清除句柄槽位中的句柄
multipleHandles.Clear(nRet - WAIT_OBJECT_0);
if (!multipleHandles.Reset()) // 重置句柄槽位
break;
}
} // end for (;;)
}// end if (!bIsFrist)
else
bIsFrist = FALSE;
clisock = aclearcase/" target="_blank" >ccept(listensock, NULL, NULL);
if (clisock == INVALID_SOCKET)
continue;
if (multipleHandles.IsFull())
{
printf("线程句柄槽位已满, 将拒绝本次客户的连接!\n");
closesocket(ClientSock);
continue;
}
hThread = CreateThread(NULL, 0, DoThread, &clisock, 0, NULL);
if (hThread == NULL)
continue;
// 将线程句柄插入到线程槽的槽位中.
multipleHandles.Insert(hThread);
}
return 0;
}
DWORD WINAPI DoThread(LVOID lpParam)
{
// 处理clisock的通信问题
// ……
}
这就是我最终解决的问题,希望大家能多给点改进的意见。