Python Asyncio连接AIS Stream时出现WebSocket握手超时问题求助
排查AIS Stream WebSocket连接超时问题
刚接触Python网络编程,能正常运行示例WebSocket代码,但连接AIS Stream(船舶数据馈送服务)获取布宜诺斯艾利斯、旧金山附近船舶数据时,每次连接均触发TimeoutError。以下是相关代码及报错栈,求帮忙排查问题原因。
代码示例
import asyncio import websockets import json from datetime import datetime, timezone async def connect_ais_stream(): try: print("Trying to connect to WebSocket...") async with websockets.connect("wss://stream.aisstream.io/v0/stream") as websocket: print("Connected to WebSocket.") subscribe_message = { "APIKey": "KEY", # ← 此处为有效API密钥 "BoundingBoxes": [ # 布宜诺斯艾利斯,阿根廷 [[-34.811548, -58.537903], [-34.284453, -57.749634]], # 旧金山,美国 [[36.989391, -123.832397], [38.449287, -121.744995]], ], "FilterMessageTypes": ["PositionReport"] } await websocket.send(json.dumps(subscribe_message)) print("Subscription message sent.") while True: try: print("Waiting for message...") message_json = await asyncio.wait_for(websocket.recv(), timeout=30) print("Message received.") message = json.loads(message_json) if "MessageType" in message: if message["MessageType"] == "PositionReport": report = message.get("Message", {}).get("PositionReport", {}) print(f"[{datetime.now(timezone.utc)}] ShipId: {report.get('UserID')} " f"Latitude: {report.get('Latitude')} Longitude: {report.get('Longitude')}") else: print("MessageType key not found.") except asyncio.TimeoutError: print("No messages received in the last 30 seconds.") except json.JSONDecodeError as e: print(f"JSON decode error: {e}") except websockets.ConnectionClosed as e: print(f"Connection closed: {e}") except Exception as e: print(f"Error: {e}") if __name__ == "__main__": asyncio.run(connect_ais_stream())
报错信息
Trying to connect to WebSocket... Traceback (most recent call last): File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\venv\Lib\site-packages\websockets\asyncio\client.py", line 541, in __await_impl__ self.connection = await self.create_connection() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\venv\Lib\site-packages\websockets\asyncio\client.py", line 467, in create_connection _, connection = await loop.create_connection(factory, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\base_events.py", line 1136, in create_connection sock = await self._connect_sock( ^^^^^^^^^^^^^^^^^^^^^^^^^ exceptions, addrinfo, laddr_infos) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\base_events.py", line 1039, in _connect_sock await self.sock_connect(sock, address) File "C:\Program Files\Python313\Lib\asyncio\proactor_events.py", line 726, in sock_connect return await self._proactor.connect(sock, address) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ asyncio.exceptions.CancelledError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\venv\Lib\site-packages\websockets\asyncio\client.py", line 539, in __await_impl__ async with asyncio_timeout(self.open_timeout): ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\timeouts.py", line 116, in __aexit__ raise TimeoutError from exc_val TimeoutError The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\client.py", line 50, in <module> asyncio.run(connect_ais_stream()) ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\runners.py", line 194, in run return runner.run(main) ~~~~~~~~~~^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\runners.py", line 118, in run return self._loop.run_until_complete(task) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ File "C:\Program Files\Python313\Lib\asyncio\base_events.py", line 720, in run_until_complete return future.result() ~~~~~~~~~~~~~^^ File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\client.py", line 9, in connect_ais_stream async with websockets.connect("wss://stream.aisstream.io/v0/stream", ping_timeout=10000) as websocket: ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\venv\Lib\site-packages\websockets\asyncio\client.py", line 587, in __aenter__ return await self ^^^^^^^^^^ File "C:\Users\GDKYCH\Jupyter\AISStream_PoC\venv\Lib\site-packages\websockets\asyncio\client.py", line 578, in __await_impl__ raise TimeoutError("timed out during opening handshake") from exc TimeoutError: timed out during opening handshake
排查方案
1. 检查网络环境
- 切换到手机热点或其他非受限网络测试,排除企业/校园网络的防火墙拦截。
- 暂时关闭本地杀毒软件、防火墙,确认是否是本地安全软件阻止了连接。
2. 延长连接超时时间
默认的握手超时时间可能不足以应对网络延迟,手动设置更长的open_timeout:
async with websockets.connect( "wss://stream.aisstream.io/v0/stream", open_timeout=60, # 延长握手超时至60秒 ping_timeout=30 ) as websocket:
3. 验证API密钥与请求格式
- 再次核对API密钥的拼写和有效性,确认在AIS Stream平台上处于激活状态。
- 检查
BoundingBoxes格式是否符合要求(官方要求每个边界框为[[最小纬度, 最小经度], [最大纬度, 最大经度]],你的坐标格式是正确的,但可以对照官方文档确认)。
4. 测试基础连通性
用curl命令测试WebSocket连接是否能建立,排除代码外的问题:
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" wss://stream.aisstream.io/v0/stream
如果curl也超时,说明是网络或服务端问题;如果能连接,再聚焦代码排查。
5. 版本兼容性排查
Python 3.13属于较新版本,可能与websockets库存在兼容性问题:
- 尝试降级Python到3.12版本测试。
- 升级websockets库到最新版:
pip install --upgrade websockets
内容的提问来源于stack exchange,提问作者mathPhys
相关产品推荐
相关产品推荐

