闲侃完成端口

  ACE是个好东东,可是真正用的时候,我还是忍不住重新造车轮。做网络层的时候,考虑了一下还是自己做吧(并不是我觉得ACE不好或不方便,只是因为自己ACE不精,怕乱舞伤了自己)。

  从好多方面来说,我都是c++的铁杆,自己给自己的评价是对c++有较深入的认识。不过因为闲时太喜欢做coding游戏,为了节省时间快速见效,投奔锐利c(c#,嘿嘿)了。扯远了,当用c#造车轮的时候,我想到了尽可能使用原生api的c++完成端口可能会对我有帮助,于是简单写了几行。

class thethe

{

public:

	bool	Init();

private:

	HANDLE	m_hiocp;	//完成端口句柄

	HANDLE	m_hworker;	//工作者线程

	static	DWORD	WINAPI	toworker(LPVOID lpthis);

	SOCKET	m_listener;		//服务器监听socket

};



bool thethe::Init()

{

	//创建服务器监听socket,必不可少的。

	sockaddr_in	listeneraddr;

	listeneraddr.sin_addr.s_addr = INADDR_ANY;

	listeneraddr.sin_family	= AF_INET;

	listeneraddr.sin_port	= htons(2350);

	m_listener	= socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

	bind(m_listener,(sockaddr*)&listeneraddr,sizeof(sockaddr_in));

	listen(m_listener,5);

					

	//1.创建完成端口句柄

	m_hiocp	= CreateIoCompletionPort(NULL,NULL,NULL,0);	

	//2.创建工作者线程

	m_hworker	= CreateThread(NULL,NULL,toworker,(LPVOID)this,0,NULL);		



	while(true)								

	{	

		SOCKET	client;



		//4.主线程循环使用accept处理新的连接

		client	= accept(m_listener,(sockaddr*)&listeneraddr,sizeof(listeneraddr));	

			//6.主线程阻塞等待下一次连接	

		perIoInfo* pif	= new perIoInfo;

		pif->sock	= client;

		//5.直接把新的连接关联到完成端口上,然后投放接受请求,直接返回

		CreateIoCompletionPort(client,m_hiocp,pif,0);						

		myoverlapped* pov = new	myoverlapped;

		pov->wbuf.buf	= pov->buf;

		pov->wbuf.len	= BUF_SIZE;

		DWORD	flag;

		//投放请求

		WSARecv(client,pov->buf,&pov->wbuf.buf,1,&flag,pov,NULL);			

		//7.操作系统在操作完成后通知完成端口

	}

}



DWORD	WINAPI thethe::toworker( LPVOID lpthis )

{

	thethe*	pthis	= static_cast<thethe*>(lpthis);



	bool	bgqcsRet;		//GetQueuedCompletionStatus结果

	DWORD	nofbytes;		//做为GetQueuedCompletionStatus的lpNumberOfBytesTransferred参数使用

	perIoInfo	comKey;		//用以满足GQCS函数的第三个参数

	LPOVERLAPPED	stoverlapped;	//满足GQCS第四个参数

	while (true)

	{

		//3.工作者线程使用阻塞模式等待完成端口信号

		bgqcsRet	= GetQueuedCompletionStatus(pthis->m_hiocp,&nofbytes,&comKey,&stoverlapped,INFINITE);	

		//8.取回刚才投放的消息

		

		//9.处理完毕后投放新的处理请求(一般是投放新的读请求)

	}

	return	0;

}

  为了把事情最简单化,我让完成端口只处理接收问题,实际使用中,listener也可以绑定在完成端口上,在完成工作者线程中处理接受新的连接工作。

  值得说明的是,GetQueuedCompletionStatus的第三个参数lpCompletionKey和CreateIoCompletionPort的第三个参数CompletionKey是同一类型,其实是在CreateIoCompletionPort中我们传入,操作系统在暂时代我们保管,在GetQueuedCompletionStatus函数中把这个参数返回。也就是说,这个参数是和句柄关联的(这里的句柄也就是socket了)。

  既然说到CompletionKey了,那就再说说GetQueuedCompletionStatus的lpOverlapped参数。对于句柄sock而已,它可以产生的信号有:accept、recv、send(close是一种特殊的recv)几种,对应的函数AcceptEx、WSARecv、WSASend都有lpOverlapped参数,秘诀就在这里,GetQueuedCompletionStatus取出了我们关心的所有信息(我们无非关心句柄、数据两部分的信息)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值