休说鲈鱼堪脍,尽西风季鹰归未?
接下来让我们继续说道:启动服务。
启动服务器-->创建释放资源线程和接收客户端请求线程(设置bServerRuning = TRUE;表示服务器启动)。
-->A.创建释放资源线程(若失败则 bServerRunning = FALSE;表示服务器结束)
-->B.创建接收客户端请求线程(若失败则 bServerRunning = FALSE;表示服务器结束)
在释放资源线程中分为两种状态
一.当服务器正在运行(bServerRuning = TRUE)
这种情况主要是为了释放那些曾经连在服务器上的客户端线程,当他们退出时,来释放他们的资源。主要描述的是,客户端主动与服务器端断开连接,服务器端来释放资源的情况。
for(;bServerRunning;) //服务器正在运行
{
EnterCriticalSection(&csClientList);
//清理已经断开的连接客户端内存空间
CLIENTLIST::iterator iter = clientlist.begin();
for(iter; iter != clientlist.end();)
{
CClient *pClient = (CClient*)*iter;
if(pClient -> IsExit()) //客户端已经退出
{
clientlist.erase(iter++);
delete pClient;
pClient = NULL;
}
else
{
iter++;
}
}
LeaveCriticalSection(&csClientList);
Sleep(TIMEFOR_THREAD_HELP);
}
二. 服务器即将退出
这种情况主要描述的是,服务器主动退出连接,释放资源的情况。这样就有两种情况,一是客户端还在与服务器连接,二是客户端没有与服务器连接。
一。先断开客户端与服务器的连接。
//断开每个连接,线程退出
EnterCriticalSection(&csClientList);
CLIENTLIST::iterator iter = clientlist.begin();
for(iter;iter != clientlist.end();)
{
CClient *pClient = (CClient*)*iter;
//如果客户端的连接还存在,则断开连接,线程退出
if(pClient -> IsConning())
{
pClient->DisConning();
}
++iter;
}
//离开临界区
LeaveCriticalSection(&csClientList);
//给连接客户端线程时间,使其自动退出
Sleep(TIMEFOR_THREAD_SLEEP);
二。收回为每个客户端分配的内存都回收。
//进入临界区
EnterCriticalSection(&csClientList);
//确保每个客户端分配的内存都回收
//如果不加入while这层循环,可能存在这样的情况,当pClient->exit()时,该线程还没有退出。
//那么就需要从链表开始部分重新判断
while(0 != clientlist.size())
{
iter = clientlist.begin();
for(iter; iter != clientlist.end();)
{
CClient *pClient = (CClient*)*iter;
if(pClient -> IsExit())
{
clientlist.erase(iter++);
delete pClient;
pClient = NULL;
}
else
{
iter++;
}
}
//给连接客户端线程时间,使其自动退出
Sleep(TIMEFOR_THREAD_SLEEP);
}
//离开临界区
LeaveCriticalSection(&csClientList);
注意,在最后我们还设置一个非常重要的事件--hServerEvent(服务器退出事件句柄)。
clientlist.clear();
SetEvent(hServerEvent);
二。创建接收客户端请求线程(是由bServerRunning控制的)
第一步:接收客户端 sAccept = accept(sServer, (SOCKADDR*)&addrClient,&lenClient);
第二步:创建客户端对象,并加入链表,并启动客户端
CClient *pClient = new CClient(sAccept,addrClient);//创建客户端对象
EnterCriticalSection(&csClientList);
clientlist.push_back(pClient); //加入链表
LeaveCriticalSection(&csClientList);
pClient -> StartRuning();