完成端口问题:线程中调用GetQueuedCompletionStatus 后,是先WSARecv再处理数据,还是先处理数据再调用WSARecv?

citywolf 2005-10-13 03:25:14
完成端口问题:线程中调用GetQueuedCompletionStatus 后,是先WSARecv再处理数据,还是先处理数据再调用WSARecv?
while(1)
{
bResult = GetQueuedCompletionStatus(
g_hCompletionPort,
&dwNumRead,
(LPDWORD)&pCntx,
&lpOverlapped,
INFINITE
);

if (bResult == FALSE
&& lpOverlapped == NULL)
{
char szLog[256];
sprintf( szLog, "Error: GetQueuedCompletionStatus failed, dwErrorCode = %d", GetLastError() );
g_Log.Log( szLog );
cout << szLog << endl;
bResult = TRUE;
continue;
}

else if (bResult == FALSE
&& lpOverlapped != NULL)
{
// This happens occasionally instead of
// end-of-file. Not sure why.
UserExit( pCntx );
continue;
}

else if (dwNumRead == 0)
{
UserExit( pCntx );
continue;
}
else
{
//数据接收
///////////////////////////////////////////////
//问题在这里,请问究竟是WSARecv完成后再调用DataProc函数进行数据处理,
//还是先DataProc数据处理后再调用WSARecv

//DataPrco(char *buf);
ZeroMemory( &pCntx->ovIn, sizeof(OVERLAPPED) );
pCntx->InDataBuf.len = MAX_READ_BYTE;
pCntx->InDataBuf.buf = pCntx->lpInBuffer;
pCntx->OperationType = RECV_POSTED;
///////////////////////////////
if( WSARecv( pCntx->sock, &pCntx->InDataBuf, 1, &dwReadNum, &dwFlags,
&pCntx->ovIn, NULL ) == SOCKET_ERROR )
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{

continue;
}
}

//
//DataProc(char *buf)
// 问题在这里,请问究竟是WSARecv完成后再调用DataProc函数进行数据处理,
//还是先DataProc数据处理后再调用WSARecv



}
}

...全文
355 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
sevencat 2005-10-17
  • 打赏
  • 举报
回复
一般是先处理再wsarecv,除非你不担心你在处理的时候,另外一个线程又收到了你刚投递的消息,然后又处理。
C_STL_C 2005-10-17
  • 打赏
  • 举报
回复
只要记住收到的信息,谁先谁后没关系。
dingpiao 2005-10-17
  • 打赏
  • 举报
回复
看 &pCntx->InDataBuf,&pCntx->ovIn 准备好没有啊
MFCBibe 2005-10-17
  • 打赏
  • 举报
回复
同意 lifengice0706(无)
先处理数据包,然后提交读请求(WSARecv())。

Delphityro 和 skykeen(天佑神州) 的解释也是对的。
skykeen 2005-10-15
  • 打赏
  • 举报
回复
WSARecv只是提交接收请求,它是异步的,它与recv()的阻塞不一样;当GetQueuedCompletionStatus()有反应时,代表原先WSARecv提交的请求的那个buf中已经有数据了,不像recv还要到socket对应的系统缓冲区同步拷贝出来
周江涛 2005-10-15
  • 打赏
  • 举报
回复
单缓冲区必须先处理数据再WSARecv,否则数据可能丢失,多缓冲的,如果你接收的和要处理的不是在同一缓冲区,则不必管先后关系。
lifengice0706 2005-10-13
  • 打赏
  • 举报
回复
先DataProc数据处理后再调用WSARecv!!
IOCP全称I/O Completion Port,文译为I/O完成端口。IOCP是一个异步I/O的API,它可以高效地将I/O事件通知给应用程序。与使用select()或是其它异步方法不同的是,一个套接字[socket]与一个完成端口关联了起来,然后就可继续进行正常的Winsock操作了。然而,当一个事件发生的时候,此完成端口就将被操作系统加入一个队列。然后应用程序可以对核心层进行查询以得到此完成端口。 大体上来讲,使用完成端口只用遵循如下几个步骤: (1) 调用 CreateIoCompletionPort() 函数创建一个完成端口,而且在一般情况下,我们需要且只需要建立这一个完成端口,把它的句柄保存好,我们今后会经常用到它…… (2) 根据系统有多少个处理器,就建立多少个工作者(为了醒目起见,下面直接说Worker)线程,这几个线程是专门用来和客户端进行通信的,目前暂时没什么工作; (3) 下面就是接收连入的Socket连接了,这里有两种实现方式:一是和别的编程模型一样,还需要启动一个独立的线程,专门用来accept客户端的连接请求;二是用性能更高更好的异步AcceptEx()请求。 (4) 每当有客户端连入的时候,我们就还是得调用CreateIoCompletionPort()函数,这里却不是新建立完成端口了,而是把新连入的Socket(也就是前面所谓的设备句柄),与目前的完成端口绑定在一起。 至此,我们其实就已经完成完成端口的相关部署工作了,嗯,是的,完事了,后面的代码里我们就可以充分享受完成端口带给我们的巨大优势,坐享其成了,是不是很简单呢? (5) 例如,客户端连入之后,我们可以在这个Socket上提交一个网络请求,例如WSARecv(),然后系统就会帮咱们乖乖的去执行接收数据的操作,我们大可以放心的去干别的事情了; (6) 而此时,我们预准备的那几个Worker线程就不能闲着了, 我们在前面建立的几个Worker就要忙活起来了,都需要分别调用GetQueuedCompletionStatus() 函数在扫描完成端口的队列里是否有网络通信的请求存在(例如读取数据,发送数据等),一旦有的话,就将这个请求从完成端口的队列取回来,继续执行本线程后面的处理代码,处理完毕之后,我们再继续投递下一个网络通信的请求就OK了,如此循环。

18,355

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧