学习笔记二,vc++创建多线程服务器(二)

休说鲈鱼堪脍,尽西风季鹰归未?

接下来让我们继续说道:启动服务。

启动服务器-->创建释放资源线程和接收客户端请求线程(设置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();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值