网络聊天项目---select模型实现

网络聊天项目—select模型实现

1.在TCPNet类里定义集合fd_set m_fdsets;
2.在TCPNet类初始化清空集合FD_ZERO(&m_fdsets);
3.将需要查看的socket加入到集合中FD_SET(socketwaiter,&m_fdsets);
在主线程监听完成之后创建一个线程等待客户端的连接,然后在连接线程函数里accept()阻塞等待,将连接上的客户端的socket(服务员和客人已连接,服务员等待客人说话)加入到集合m_fdsets中。

  1. 出现问题:整个集合交给select管理,select管理一段时间后返回,假如没有一个socket发生网络事件,数组(集合)就空了,下次再让查看socket换需要再将socket加入到集合中,这样每次初始化数组集合太麻烦。
  2. 解决办法:在recv接收数据线程函数里边定义一个临时的集合,将已初始化好的集合赋值给temp临时集合,每次将临时集合交给select管理,然后再次初始化用开始的集合给temp赋值。

4.将集合交给select管理select();定时查看有没有可读数据。在主线程创建等待连接客户端的线程后创建一个接收数据的线程,然后在接收数据线程函数里定义一个临时集合fd_set m_fdtemp,将集合赋值给临时集合,然后将临时集合交给select管理。select在内核里定时查看设定的时间,将发生网络事件的socket留在集合中返回。
5.检验是否发生网络事件,FD_ISSET();因为socket是一个链表需要循环查看。
如果发生网络事件就去处理,然后select继续查看。

unsigned __stdcall TCPNet::ThreadRecv( void * lpvoid)
{
	TCPNet *pthis = (TCPNet*)lpvoid;
	//接受数据
	SOCKET sockWaiter = (SOCKET)lpvoid;
	int nBufferSize;
	int nRes;
	char *pszbuf = NULL;
	fd_set fdtemp;
	timeval tv;
	tv.tv_sec = 0;
	tv.tv_usec = 100;
	while(TCPNet::m_bFlagQuit)
	{
		fdtemp = pthis->m_fdsets;
		//将整个集合交给select管理
		select(0,&fdtemp,0,0,&tv);
		//检验是否发生网络事件  socket是一个链表,循环遍历
		for(int i=0;i<pthis->m_fdsets.fd_count;i++)
		{
			if(FD_ISSET(pthis->m_fdsets.fd_array[i],&fdtemp))
			{
				nRes = recv(pthis->m_fdsets.fd_array[i],(char *)&nBufferSize,sizeof(int),0);
				//int nRes = recv(sockWaiter,szbuf,sizeof(szbuf),0);
				if(nRes <= 0)
					continue;
				//首先根据接收到的包大小申请相应的空间
				pszbuf = new char[nBufferSize];
				int offset = 0;
				while(nBufferSize)
				{
										/*从首地址开始放数据*/
					nRes = recv(pthis->m_fdsets.fd_array[i],pszbuf+offset,nBufferSize,0);
					offset += nRes;
					nBufferSize -= nRes;
				}
				//处理
				m_pKernel->DealData(pszbuf,pthis->m_fdsets.fd_array[i]);
			}
		}

		delete []pszbuf;
		pszbuf = NULL;
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值