完成端口 GetQueuedCompletionStatus 异常处理

公司的校园平安卡产品,C/S结构,客户端数目大概50个,服务端采用IOCP(完成端口)与客户端通信,Socket UDP协议。

服务端程序基本流程:
 1.程序建立IOCP模型并绑定Socket,用WSARecvFrom 向IOCP通道中投递数据接收请求
 2.Work线程,整体是循环:使用GetQueuedCompletionStatus获取通道中已经完成的请求和数据,然后有一个判断:
     如果取到的是接收结果,则将收到的数据保存到接收队列,然后使用WSARecvFrom 继续投递数据接收请求
     如果取到的不是接收结果,则不做处理
 3.Work线程接收到的数据,经过加工,生成需要发送的数据,存进发送队列    
 4.Send线程,也是循环:从发送队列取数据,用WSASendTo投递发送请求

   GetQueuedCompletionStatus有时会返回error 1234,含义是“没有任何服务正在远程系统上的目标网络终结点上操作”,原因可能是某个客户端与服务端连接异常。原先服务端遇到GetQueuedCompletionStatus出错时是直接return,退出线程,然后关闭整个程序。另外有一个进程监控程序(负责监控服务器上各应用程序状态,发现应用程序退出后便将其重新启动)随后将平安卡服务端程序重新启动。GetQueuedCompletionStatus错误是偶尔出现,基本不影响正常运行。

     但是遇到某个客户端设备调试或者网络调整,GetQueuedCompletionStatus就会不断出错,导致服务端程序频繁重启,无法正常运行。因此要调整Work线程的逻辑,在GetQueuedCompletionStatus出错后记录错误信息但不要退出程序,继续保持与其他客户端的通信

    最开始考虑的很简单,是在GetQueuedCompletionStatus返回error后记下log,然后直接countinue到下一次循环。这样修改后实际运行时发现,GetQueuedCompletionStatus 返回error后程序虽然没有退出,但是却停止了与各个客户端的通信。
    分析原因:Work线程GetQueuedCompletionStatus出错后直接countinue跳到下一次循环,没有投递数据接收请求,则GetQueuedCompletionStatus取不到数据接收结果,陷入阻塞,于是数据收发也都停下了。
   重新调整,在GetQueuedCompletionStatus出错后用WSARecvFrom 投递接收请求,再执行countinue,运行验证,GetQueuedCompletionStatus再出错时程序可以继续保持与其他客户端的通信了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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了,如此循环。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
完成端口Completion Port)是一种高效的 I/O 模型,它充分利用了操作系统 I/O 处理的异步特性,可以在一个线程池中处理大量的 I/O 操作,提高系统的并发处理能力。下面是一个使用完成端口模型的简单程序设计示例: 1. 初始化完成端口 ```csharp HANDLE completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); ``` 2. 创建一组工作线程 ```csharp for (int i = 0; i < numThreads; i++) { HANDLE threadHandle = CreateThread(NULL, 0, WorkerThread, completionPort, 0, NULL); CloseHandle(threadHandle); } ``` 3. 向完成端口投递异步 I/O 请求 ```csharp // 打开文件 HANDLE fileHandle = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); // 创建 OVERLAPPED 结构体 OVERLAPPED *overlapped = new OVERLAPPED; ZeroMemory(overlapped, sizeof(OVERLAPPED)); // 向完成端口投递异步读取请求 ReadFileEx(fileHandle, buffer, bufferSize, overlapped, CompletionRoutine); ``` 4. 工作线程处理完成端口完成通知 ```csharp DWORD WorkerThread(LPVOID lpParam) { HANDLE completionPort = (HANDLE) lpParam; DWORD numBytes; ULONG_PTR completionKey; LPOVERLAPPED overlapped; while (GetQueuedCompletionStatus(completionPort, &numBytes, &completionKey, &overlapped, INFINITE)) { // 处理完成通知 CompletionRoutine(numBytes, completionKey, overlapped); } return 0; } ``` 5. 完成例程处理异步 I/O 请求的完成 ```csharp VOID CALLBACK CompletionRoutine(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { // 处理异步 I/O 请求的完成 } ``` 以上是一个简单的完成端口模型程序设计示例,具体实现需要根据实际需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值