5.4.4清理资源线程

  清理资源线程用于清理为每个接收的客户端分配的资源。由HelperThread()函数实现。该函数工作于服务器两种状态下。

1.服务器正在运行

在一个for循环中,将管理客户端连接clientlist链表的节点依次取出,然后调用CClient类的IsExit()函数。如果返回值为TRUE,说明该客户端的连接已经关闭,将该节点从clientlist链表中删除,并释放客户端连接实例占用的内存空间。

2.服务器即将退出

服务器退出时,必须保证在主线程退出之前,所以子线程全自动然退出。当用户输入字符“e”或者“E”时,在StopService()函数中,修改bServerRunning变量值为FALSE。然后,调用WaitForSingleObject()函数,等待清理资源线程发送的事件通知。

接受客户端请求线程,判断bServerRunning变量值为FALSE,该线程退出。

清理资源线程,负责通知所有与客户端连接的线程自动退出。执行过程执行如下。

1)从前面所述的for循环体中跳出。

2)在第二个for循环体中,从clientlist链表依次取出连接客户端实例节点。调用DisConning()函数,将处于连接状态的客户端断开,使与该客户端连接的数据接收和发送线程退出。

3)在第三个for循环体中,释放所有为CClient类实例分配的内存空间。

4)调用SetEvent()函数,设置hServerEvent事件对象为有信号状态,通知主线程可以退出。HelperThread()线程函数的程序清单如下。

/**

 * 清理资源

 */

DWORD __stdcall HelperThread(void* pParam)

{

         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);

         }

 

 

         //服务器停止工作

         if (!bServerRunning)

         {

                   //断开每个连接,线程退出

                   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->IsExit()时,该线程还没有退出。

                   //那么就需要从链表的开始部分重新判断。

                   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);                                     //离开临界区

         }

        

         clientlist.clear();                                                                                   //清空链表

        

         SetEvent(hServerEvent);                                                           //通知主线程退出

         return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值