admin管理员组

文章数量:1531791

2023年12月13日发(作者:)

完成端口GetQueuedCompletionStatus异常处理

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

服务端程序基本流程:

1.程序建立IOCP模型并绑定Socket,用WSARecvFrom 向IOCP通道中投递数据接收请求

线程,整体是循环:使用GetQueuedCompletionStatus获取通道中已经完成的请求和数据,然后有一个判断:

如果取到的是接收结果,则将收到的数据保存到接收队列,然后使用WSARecvFrom 继续投递数据接收请求

如果取到的不是接收结果,则不做处理

线程接收到的数据,经过加工,生成需要发送的数据,存进发送队列

线程,也是循环:从发送队列取数据,用WSASendTo投递发送请求

GetQueuedCompletionStatus有时会返回error 1234,含义是“没有任何服务正在远程系统上的目标网络终结点上操作”,原因可能

是某个客户端与服务端连接异常。原先服务端遇到GetQueuedCompletionStatus出错时是直接return,退出线程,然后关闭整个程序。

另外有一个进程监控程序(负责监控服务器上各应用程序状态,发现应用程序退出后便将其重新启动)随后将平安卡服务端程序重新启动。

GetQueuedCompletionStatus错误是偶尔出现,基本不影响正常运行。

但是遇到某个客户端设备调试或者网络调整,GetQueuedCompletionStatus就会不断出错,导致服务端程序频繁重启,无法正常运

行。因此要调整Work线程的逻辑,在GetQueuedCompletionStatus出错后记录错误信息但不要退出程序,继续保持与其他客户端的通信

最开始考虑的很简单,是在GetQueuedCompletionStatus返回error后记下log,然后直接countinue到下一次循环。这样修改后实际

运行时发现,GetQueuedCompletionStatus 返回error后程序虽然没有退出,但是却停止了与各个客户端的通信。

分析原因:Work线程GetQueuedCompletionStatus出错后直接countinue跳到下一次循环,没有投递数据接收请求,则

GetQueuedCompletionStatus取不到数据接收结果,陷入阻塞,于是数据收发也都停下了。

重新调整,在GetQueuedCompletionStatus出错后用WSARecvFrom 投递接收请求,再执行countinue,运行验

证,GetQueuedCompletionStatus再出错时程序可以继续保持与其他客户端的通信了。

本文标签: 数据程序接收投递客户端