在IOCP中使用GetQueuedCompletionStatus函数的问题。

Chevin 2009-04-01 10:36:12
在MSDN中,关于GetQueuedCompletionStatus函数返回值的描述如下:

1.
If the function dequeues a completion packet for a successful I/O operation from the completion port, the return value is nonzero. The function stores information in the variables pointed to by the lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped parameters.
如果函数从完成端口取出一个成功I/O操作的完成包,返回值为非0。函数在指向lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped的参数中存储相关信息。



2.
If *lpOverlapped is NULL and the function does not dequeue a completion packet from the completion port, the return value is zero. The function does not store information in the variables pointed to by the lpNumberOfBytesTransferred and lpCompletionKey parameters. To get extended error information, call GetLastError. If the function did not dequeue a completion packet because the wait timed out, GetLastError returns WAIT_TIMEOUT.
如果 *lpOverlapped为空并且函数没有从完成端口取出完成包,返回值则为0。函数则不会在lpNumberOfBytes and lpCompletionKey所指向的参数中存储信息。调用GetLastError可以得到一个扩展错误信息。如果函数由于等待超时而未能出列完成包,GetLastError返回WAIT_TIMEOUT.



3.
If *lpOverlapped is not NULL and the function dequeues a completion packet for a failed I/O operation from the completion port, the return value is zero. The function stores information in the variables pointed to by lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped. To get extended error information, call GetLastError
如果 *lpOverlapped不为空并且函数从完成端口出列一个失败I/O操作的完成包,返回值为0。函数在指向lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped的参数指针中存储相关信息。调用GetLastError可以得到扩展错误信息



4.
If a socket handle associated with a completion port is closed, GetQueuedCompletionStatus returns ERROR_SUCCESS, with lpNumberOfBytes equal zero.
如果关联到一个完成端口的一个socket句柄被关闭了,则GetQueuedCompletionStatus返回ERROR_SUCCESS,并且lpNumberOfBytes等于0


在以上4中情况中,1、2、4都能模拟实现出来,但是在什么情况下,才会出现第3中情况呢?
“失败I/O操作的完成包”是指的什么呢?
...全文
363 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
Chevin 2009-04-02
  • 打赏
  • 举报
回复
谢谢。

“完成队列是按投递先后有序的,至于消息谁先返回,那要看那个消息先完成。”
你的意思是不是,对同一个socket先投递RecvA,后投递RecvB,(假设RecvA和RecvB的buffer大小都为10byte)。那么,传过来的数据是18byte的话,那么RecvA一定是先收到前面的10Byte,而RecvB一定是接着收到后面的8Byte???
至于谁先返回到用户就说不定了,是吧?



“建议你详细的看看MSDN上关于IOCP的描述。”
请问,MSDN那里有比较详细的介绍IOCP原理的呢?
我现在是一个函数一个函数的看。

主要是对同一个socket投递多个Recv比较疑惑。
rularys 2009-04-02
  • 打赏
  • 举报
回复
"另外,如果我想再了解一下一次投递多个Recv,是否先投递的一定先接收到消息呢???
比如Post了两个,先RevcA、后RecvB,那么RecvA肯定是比RecvB先接收到消息的吗?"

完成队列是按投递先后有序的,至于消息谁先返回,那要看那个消息先完成。
建议你详细的看看MSDN上关于IOCP的描述
Chevin 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 rulary 的回复:]
failed I/O operation

假如线程T投递了异步I/O操作i并且该操作正在被等待中,这时候线程T退出或者取消了I/O操作,那么i就会失败
返回。
[/Quote]

谢谢回复。
我进行了如下尝试,在一个线程中POST了一个Recv,那么这个Recv肯定是等待的(客户端只连接,不发送数据),然后等一段事件,这个线程退出了。
CancelIO方法,也是如下结果。
结果如下:
1.GetQueuedCompletionStatus返回false
2.lpNumberOfBytes=0
3.lpOverlapped!=NULL
4lpCompletionKey!=NULL

非常感谢了。
另外,如果我想再了解一下一次投递多个Recv,是否先投递的一定先接收到消息呢???
比如Post了两个,先RevcA、后RecvB,那么RecvA肯定是比RecvB先接收到消息的吗?

rularys 2009-04-01
  • 打赏
  • 举报
回复
failed I/O operation

假如线程T投递了异步I/O操作i并且该操作正在被等待中,这时候线程T退出或者取消了I/O操作,那么i就会失败
返回。
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了,如此循环。

64,652

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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