asyncua异步连接PLC端OPCUA服务器超时问题求助
异步OPC UA客户端连接超时(含CancelledError)问题排查
问题背景
在Windows 10 x64环境下使用asyncua库连接PLC部署的OPC UA服务器时,同步代码可正常建立连接,但异步代码调用await client.connect()会抛出包含asyncio.exceptions.CancelledError的TimeoutError。其他第三方OPC UA客户端均可正常连接该服务器,且异步代码中若不使用await调用节点方法,会返回协程对象而非预期的数值/布尔值。
同步正常连接代码
client = Client("opc.tcp://192.168.1.88:4840") # client.max_chunkcount = 5000 # in case of refused connection by the server # client.max_messagesize = 16777216 # in case of refused connection by the server client.connect()
错误日志
disconnect_socket was called but connection is closed close_session was called but connection is closed close_secure_channel was called but connection is closed disconnect_socket was called but connection is closed Traceback (most recent call last): File "Python311\Lib\asyncio\tasks.py", line 490, in wait_for return fut.result() ^^^^^^^^^^^^ asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "OPCgpt.py", line 28, in <module> loop.run_until_complete(connect_to_opc_server()) File "Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "OPCgpt.py", line 12, in connect_to_opc_server await client.connect() File "Python311\Lib\site-packages\asyncua\client\client.py", line 287, in connect await self.open_secure_channel() File "Python311\Lib\site-packages\asyncua\client\client.py", line 374, in open_secure_channel result = await self.uaclient.open_secure_channel(params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "Python311\Lib\site-packages\asyncua\client\ua_client.py", line 315, in open_secure_channel return await self.protocol.open_secure_channel(params) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "Python311\Lib\site-packages\asyncua\client\ua_client.py", line 232, in open_secure_channel await asyncio.wait_for(self._send_request(request, message_type=ua.MessageType.SecureOpen), self.timeout) File "Python311\Lib\asyncio\tasks.py", line 492, in wait_for raise exceptions.TimeoutError() from exc TimeoutError
复现代码
import asyncio from asyncua import Client async def connect_to_opc_server(): # 创建OPC UA客户端 client = Client(url="opc.tcp://192.168.1.88:4840") # client.max_chunkcount = 5000 # client.max_messagesize = 16777216 client.name = "Re_Shoes" try: # 连接OPC UA服务器 await client.connect() # 列出根节点的所有子节点 root_node = await client.get_root_node() print("root node is: ", root_node) finally: # 断开与服务器的连接 await client.disconnect() if __name__ == "__main__": loop = asyncio.get_event_loop() loop.run_until_complete(connect_to_opc_server()) loop.close()
可能原因及解决方案
1. 异步客户端超时设置过短
asyncua异步客户端默认超时时间可能不足以应对PLC服务器的响应延迟,手动增加超时时间:
client = Client(url="opc.tcp://192.168.1.88:4840") client.timeout = 30 # 调整为30秒,根据实际网络情况修改
2. Windows异步事件循环兼容性问题
Windows 10默认的asyncio事件循环在部分场景下存在兼容性问题,改用ProactorEventLoop:
if __name__ == "__main__": asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) loop = asyncio.get_event_loop() loop.run_until_complete(connect_to_opc_server()) loop.close()
3. 未同步设置连接参数
同步代码中注释的max_chunkcount和max_messagesize参数可能是连接PLC服务器的必要配置,取消注释并启用:
client.max_chunkcount = 5000 client.max_messagesize = 16777216
4. 服务器对异步请求的特殊限制
部分PLC的OPC UA服务器对异步请求的处理逻辑与同步不同,启用调试日志查看详细交互过程:
import logging logging.basicConfig(level=logging.DEBUG)
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

