You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:05:56