完成端口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的返回值的更多相关文章

  1. socket读写返回值的处理

    在调用socket读写函数read(),write()时,都会有返回值.如果没有正确处理返回值,就可能引入一些问题 总结了以下几点 1当read()或者write()函数返回值大于0时,表示实际从缓冲 ...

  2. Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示

    Dapper的牛逼就不扯蛋了,答应群友做个入门Demo的,现有园友需要,那么公开分享一下: 完整Demo:http://pan.baidu.com/s/1i3TcEzj 注 意 事 项:http:// ...

  3. 由Dapper QueryMultiple 返回数据的问题得出==》Dapper QueryMultiple并不会帮我们识别多个返回值的顺序

    异常汇总:http://www.cnblogs.com/dunitian/p/4523006.html#dapper 今天帮群友整理Dapper基础教程的时候手脚快了点,然后遇到了一个小问题,Dapp ...

  4. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  5. Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值

    Asp.net中存储过程拖拽至dbml文件中,提示无法获得返回值,去属性表中设置这时候会提示你去属性表中更改返回类型. 其实存储过程返回的也是一张表,只不过有时候存储过程有点复杂或者写法不规范的话不能 ...

  6. SubSonic3.0使用存储过程查询时,不能使用output参数返回值的问题修改

    有个群友问SubSonic3.0执行存储过程时能不能使用output参数返回值,说测试过后获取不到返回值,早上有些时间所以就尝试修改了一下 首先在数据库中创建一个存储过程 CREATE PROCEDU ...

  7. 支持多返回值存储过程的SqlHelper

    public readonly string connStr = ConfigurationManager.ConnectionStrings["sql"].ConnectionS ...

  8. sql语句返回值的问题

    由于执行sql语句的时候执行成功或者失败会返回执行的影响函数,用list是因为查询的结果可能为null也可能set后放到集合里去: 所以返回值类型用int

  9. JsonResult作为Action返回值时的错误

    JsonResult作为Action返回值时的错误   System.InvalidOperationException: This request has been blocked because ...

随机推荐

  1. 【转】Linux高级字符设备之Poll操作

    原文网址:http://www.cnblogs.com/geneil/archive/2011/12/04/2275559.html 在用户程序中,select()和poll()也是与设备阻塞与非阻塞 ...

  2. 微软官方的一段JavaScript判断.net环境

    <HTML> <HEAD> <TITLE>Test for the .NET Framework 3.5</TITLE> <META HTTP-E ...

  3. js记录用户在网站的浏览记录和停留时间

    by weber开发者 from http://weber.pub/ 本文地址: http://weber.pub/js记录用户行为浏览记录和停留时间/163.html 问题 公司想统计一个用户从进入 ...

  4. c# 读取其他程序的ListView内容

    ArcMap没找到一个导出图层字段结构的功能,自已花点时间用C#做了个小工具,专门用来导arcmap中图层属性面板中的字段信息. 使用说明: 1) 点击“查找窗口”按钮.2) 在ListView控件上 ...

  5. [转] C#中的Dictionary的使用

    txw1958 的 原文 说明    必须包含名空间System.Collection.Generic     Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)     键 ...

  6. Nginx 反向代理、负载均衡、页面缓存、URL重写、读写分离及简单双机热备详解

    大纲 一.前言 二.环境准备 三.安装与配置Nginx  (windows下nginx安装.配置与使用) 四.Nginx之反向代理 五.Nginx之负载均衡  (负载均衡算法:nginx负载算法 up ...

  7. Yii 实现MySQL多库和读写分离

    前段时间为SNS产品做了架构设计,在程序框架方面做了不少相关的压力测试,最终选定了YiiFramework,至于为什么没选用公司内部的PHP框架,其实理由很充分,公司的框架虽然是“前辈”们辛苦的积累, ...

  8. C++重要知识点小结---2

    C++重要知识点小结--1 :http://www.cnblogs.com/heyonggang/p/3246631.html 1.C++允许程序员声明一个不能有实例对象的类,这样的类惟一的用途是被继 ...

  9. 使用python三方库xlrd解析excel数据

    excel是平常用的比较多的一种数据格式,而在自动化测试过程中,解析其数据以供脚本使用就是一个重要的工作,幸好已有现存的三方库供使用,而不必重新造轮子. 一.安装xlrd模块 到python官网下载h ...

  10. <转>安卓应用测试checklist

    启动: 1. 启动入口:桌面正常启动,最近运行启动,所有程序列表中启动,锁屏快捷启动 2. 其他入口:从其他程序开启应用,从外部以文件形式打开应用(如果有) 3. 退回:从其他程序退回时回到被测应用, ...