调用 WebSocket API 延长 ListenKey 失败

返回提示为:

{{
“code”: 2,
“msg”: “Invalid request: unknown variant userDataStream.ping,
expected one of SUBSCRIBE, UNSUBSCRIBE, LIST_SUBSCRIPTIONS, SET_PROPERTY, GET_PROPERTY, REQUEST
}}

好像不接受userDataStream.ping作为请求参数,这是为何?

The error message you’re receiving indicates that the userDataStream.ping variant is not recognized as a valid request parameter by the system you are interfacing with. It expects one of the following commands: SUBSCRIBE, UNSUBSCRIBE, LIST_SUBSCRIPTIONS, SET_PROPERTY, GET_PROPERTY, or REQUEST.

This typically occurs when you’re interacting with a WebSocket or an API that has predefined acceptable commands or request types. The userDataStream.ping you attempted to use is not among the accepted commands, which is why you received an error.

If you’re trying to maintain the connection or check the liveliness of the stream, you might be using a custom or incorrect command. Usually, WebSocket connections are maintained with a simple ping command, not a prefixed command like userDataStream.ping.

Here is a revised version Python code that incorporates a WebSocket connection to Binance for monitoring cryptocurrency trading data. I have simplified and annotated the code to make it more user-friendly and focused on your specific needs. This code handles the ping-pong mechanism automatically and maintains the listen key alive, which are critical for uninterrupted data streams in real-time trading scenarios.

import asyncio
import websockets
import logging
import json

Setup basic logging

logging.basicConfig(level=logging.INFO)

Reconnection interval set to 23 hours

RECONNECTION_INTERVAL = 23 * 60 * 60

async def create_listen_key(client):
“”“Create a listen key for Binance user data stream.”“”
response = await client.create_user_data_stream() # Placeholder function, replace with actual API call
if ‘listenKey’ in response:
return response[‘listenKey’]
logging.error(f"Failed to obtain listen key: {response}")
return None

async def keep_listen_key_alive(client, listen_key):
“”“Keep the listen key alive by sending a keep-alive command every 30 minutes.”“”
while True:
await asyncio.sleep(30 * 60) # Sleep for 30 minutes
try:
await client.keepalive_user_data_stream(listen_key) # Placeholder function, replace with actual API call
logging.info(“Successfully sent keep-alive for listen key.”)
except Exception as e:
logging.error(f"Error sending keep-alive: {str(e)}")
break # Exit the loop if there’s an error

async def delete_listen_key(client, listen_key):
“”“Delete the listen key.”“”
try:
await client.close_user_data_stream(listen_key) # Placeholder function, replace with actual API call
logging.info(“Listen key deleted successfully.”)
except Exception as e:
logging.error(f"Failed to delete listen key: {str(e)}")

async def connect_websocket(client, listen_key):
“”“Connect to WebSocket using the listen key.”“”
ws_url = f"wss://stream.binance.com:9443/ws/{listen_key}"
async with websockets.connect(ws_url, ping_interval=None) as ws: # Disabling auto ping
try:
# Here you would handle incoming messages
while True:
response = await ws.recv()
message = json.loads(response)
logging.info(f"Received message: {message}")
# Process each message here
except websockets.exceptions.ConnectionClosed:
logging.error(“WebSocket connection closed unexpectedly.”)

async def main(client):
“”“Main function to manage WebSocket connection.”“”
listen_key = await create_listen_key(client)
if listen_key:
keep_alive_task = asyncio.create_task(keep_listen_key_alive(client, listen_key))
try:
await connect_websocket(client, listen_key)
finally:
keep_alive_task.cancel()
await delete_listen_key(client, listen_key)
else:
logging.error(“Failed to create listen key, cannot proceed.”)

Example client class

class ExampleClient:
“”“Example client class to simulate Binance API client methods.”“”
async def create_user_data_stream(self):
return {“listenKey”: “your_listen_key_here”} # Simulate API response

async def keepalive_user_data_stream(self, listen_key):
    logging.info("Simulated keepalive call.")

async def close_user_data_stream(self, listen_key):
    logging.info("Simulated close stream call.")

client = ExampleClient() # Replace with your actual Binance client instance

Run the main function with asyncio

asyncio.run(main(client))


Replace placeholder methods with actual methods from your Binance client library. This example assumes that you have a client object (client) that interacts with Binance’s API. If your setup or library differs, you will need to adjust the API calls accordingly.

Keepalive User Data Stream(Websocket API) | Binance Open Platform

多谢您的答复。依据上述文档,userDataStream.ping 应该是可以接受的参数,但是却返回了错误,不知为何?期待您的进一步指导,多谢!

to be safe, I have not taken max 60 min, if you want you can use 60min or 59min, its upto you, this will extend the websocket connection by 60 min… Binance require listen Keep alive within 60 mins…

async def keep_listen_key_alive_loop(client, listen_key):
while True:
await asyncio.sleep(30 * 60) # Sleep for 30 minutes
await keep_listen_key_alive(client, listen_key)

The below line of code you have to use which will automatically send the ping every 3mins (below 180 is seconds)…

        ws_url = f"wss://stream.binance.com:9443/ws/{listen_key}"
        async with websockets.connect(ws_url, ping_interval=180, ping_timeout=600) as websocket:
            await subscribe_to_kline_stream(websocket, symbol, interval)