GetQueuedCompletionStatus的返回值
完成端口GetQueuedCompletionStatus返回值的问题
先看看GetQueuedCompletionStatus函数的完整声明:
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED *lpOverlapped,
DWORD dwMilliseconds
);
再看看MSDN上对其返回值的说明:
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的参数中存储相关信息。
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.
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可以得到扩展错误信息
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
相应的,我处理的方式:
while(){
flag=GetQueuedCompletionStatus(
HANDLE CompletionPort,
LPDWORD lpNumberOfBytes,
PULONG_PTR lpCompletionKey,
LPOVERLAPPED *lpOverlapped,
DWORD dwMilliseconds
);
针对:如果 *lpOverlapped为空并且函数没有从完成端口取出完成包,返回值则为0。函数则不会在lpNumberOfBytes and lpCompletionKey所指向的参数中存储信息。
if(lpOverlapped== NULL) {continue;}
针对: 如果
*lpOverlapped不为空并且函数从完成端口出列一个失败I/O操作的完成包,返回值为0。函数在指向
lpNumberOfBytesTransferred, lpCompletionKey, and
lpOverlapped的参数指针中存储相关信息。调用GetLastError可以得到扩展错误信息
if(FALSE == flag && GetLastError()!=0){ 归还IO句柄;continue;}
针对:如果关联到一个完成端口的一个socket句柄被关闭了,则GetQueuedCompletionStatus返回ERROR_SUCCESS,并且lpNumberOfBytes等于0 .
ERROR_SUCCESS这个值是0,即返回值是0(false)且GetLastError()等于0,与上面的错误处理代码是有分别的。
if(opType != IO_ACCEPT && dwByteTrans == 0) {做断开处理,归还IO;continue;}
针对: 如果函数从完成端口取出一个成功I/O操作的完成包,返回值为非0。函数在指向lpNumberOfBytesTransferred, lpCompletionKey, and lpOverlapped的参数中存储相关信息。
switch(){根据IO类型做相关操作}
}
现在的问题是:我需要在(FALSE == flag &&
GetLastError()!=0)的情况下做一些处理。导致GetQueuedCompletionStatus返回失败的因素有很多,最常见的是
〖1236〗-由本地系统终止网络连接,〖1234〗-没有任何服务正在远程系统上的目标网络终结点上操作,〖64〗-指定的网络名不再可用等等。之前发
生错误时简单的回还IO句柄,但有些问题由此而产生。
1.WSASEND/WSARECV调用成功,但实际上IO被重置,GetQueuedCompletionStatus返回错误。
2.服务器主动关闭了socket,导致投递的io返回。
3.由其他原因导致io失败等。如udp等待接收的socket会发生997错误:重叠 I/O 操作在进行中。(这个也不好理解,为什么接收在进行却返回?应该阻塞等待其完成返回啊)
之前没想到udp等待接收的IO会失败返回,于是未加区分的归还IO了事。(面向终端的tcp的io请求失败后,由于终端重连时会继续投递接收请
求,因此面向终端的一边是没有问题的)导致后期udp
socket没有接收请求投递而收不到任何数据。因此需要在这个错误处理过程中区分IO类型分别做处理。这里复杂的原因在于该完成端口绑定了tcp
socket,udp socket,等待连接的socket,主动连接的socket等等这些类型,用途各异的socket。
这样,需要在udp请求IO失败后主动的重新投递接收请求,主动地向服务器发送。在此过程中需要取完成键,一个奇怪的现象产生了,此时的完成键
lpCompletionKey有时候为NULL。按照MS的说法:如果
*lpOverlapped不为空并且函数从完成端口出列一个失败I/O操作的完成包,返回值为0。函数在指向
lpNumberOfBytesTransferred, lpCompletionKey,
lpOverlapped的参数指针中存储相关信息。如果*lpOverlapped为空,则参数不赋值。而我在前一种情况下的完成键却是NULL,并未
赋值。之前没考虑,从中取值导致程序时常崩溃,现在加入判断则恢复正常.
但是为什么完成键在IO句柄不为空的情况下没有赋值?这个问题依然不解,而且对我的系统而言仍然有隐忧。我是在完成键赋值的情况下会重新投递面向IAG的udp接收请求,若完成键没有赋值,投递io没有进行,后期的数据会收不到。这种情况虽然没有发生,但是是有可能的。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wangandy7811/archive/2009/12/03/4930885.aspx
GetQueuedCompletionStatus的返回值的更多相关文章
- socket读写返回值的处理
在调用socket读写函数read(),write()时,都会有返回值.如果没有正确处理返回值,就可能引入一些问题 总结了以下几点 1当read()或者write()函数返回值大于0时,表示实际从缓冲 ...
- Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示
Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http:// ...
- 由Dapper QueryMultiple 返回数据的问题得出==》Dapper QueryMultiple并不会帮我们识别多个返回值的顺序
异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#dapper 今天帮群友整理Dapper基础教程的时候手脚快了点,然后遇到了一个小问题,Dapp ...
- C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解 ...
- Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值
Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值,去属性表中设置这时候会提示你去属性表中更改返回类型. 其实存储过程返回的也是一张表,只不过有时候存储过程有点复杂或者写法不规范的话不能 ...
- SubSonic3.0使用存储过程查询时,不能使用output参数返回值的问题修改
有个群友问SubSonic3.0执行存储过程时能不能使用output参数返回值,说测试过后获取不到返回值,早上有些时间所以就尝试修改了一下 首先在数据库中创建一个存储过程 CREATE PROCEDU ...
- 支持多返回值存储过程的SqlHelper
public readonly string connStr = ConfigurationManager.ConnectionStrings["sql"].ConnectionS ...
- sql语句返回值的问题
由于执行sql语句的时候执行成功或者失败会返回执行的影响函数,用list是因为查询的结果可能为null也可能set后放到集合里去: 所以返回值类型用int
- JsonResult作为Action返回值时的错误
JsonResult作为Action返回值时的错误 System.InvalidOperationException: This request has been blocked because ...
随机推荐
- smarty分页模板(用模板语法写分页)
分页是一个我们经常要用到的.比较基本的小功能,你可以通过定义一个方法或类来对它进行封装.重用.而本文则是通过利用smarty独有的语法,以模版的方式进行封装,从而达到同样的目的. 下面开始具体实现步骤 ...
- Android 系统 reboot
/*********************************************************************** * Android 系统 reboot * 说明: * ...
- 剑指offer-第二章算法之斐波拉契数列(青蛙跳台阶)
递归与循环 递归:在一个函数的内部调用这个函数. 本质:把一个问题分解为两个,或者多个小问题(多个小问题相互重叠的部分,会存在重复的计算) 优点:简洁,易于实现. 缺点:时间和空间消耗严重,如果递归调 ...
- Java中SynchronizedMap与ConcurrentHashMap的对比
如何使用 概述 ConcurrentHashMap: 线程安全: 其将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都 ...
- 中小型数据库 RMAN CATALOG 备份恢复方案(二)
中小型数据库呈现的是数据库并发少,数据库容量小,版本功能受限以及N多单实例等特点.尽管如此,数据库的损失程度也会存在零丢失的情形.企业不愿意花太多的钱又要保证数据库的可靠稳定,可是苦煞了我这些搞DB的 ...
- 下载个jquery-easyui-1.3.0使用,把他导入到myeclipse10里,jquery-1.7.2.min.js报错。 错误如下, Syntax error on token "Invalid Regular Expression Options", no accurate correc
1.选中报错的jquery文件“jquery-1.2.6.min.js”.2.右键选择 MyEclipse-->Exclude From Validation .3.再右键选择 MyEclips ...
- ubuntu 切换工作区域
在Ubuntu 13.04中,默认是不激活多桌面工作空间的,所以在之前的版本可以在启动器看到的那个像“田”字的“工作区切换器”图标没有了,始终只有一个桌面了.要激活工作空间,在system setti ...
- MySQL · 性能优化· InnoDB buffer pool flush策略漫谈
MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...
- sqlserver数据可空插入报错
数据库和C#中均为可空类型. 这时候直接给字段赋值为null parameters[9].Value = null : 执行的时候报错了,一大堆,总之说它少了一个参数. 用sql ser ...
- ifstream 流 判断文件是否结尾的函数eof(.xml
pre{ line-height:1; color:#800080; font-size:16px;}.sysFunc{color:#627cf6;font-style:italic;font-wei ...