Python-binance: Unable to restart websocket, and reconnection issues.

Created on 2 Mar 2018  路  17Comments  路  Source: sammchardy/python-binance

When attempting to end a single websocket with bm.close() or bm_.stop_socket(conn_key), after attempting to start a new socket I do not receive any data from the callback, meaning the socket is not connecting, and BinanceSocketManager must not be working correctly.

bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()
#Runs fine until I would like to stop and connect.
bm.stop_socket(conn_key)
conn_key = bm.start_trade_socket('BNBBTC', process_message )

or if I used bm.close():

bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()
bm.close()
bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()

I have added time.sleep(60) lines between the stop and start calls, but they don't seem to help. I still end up receiving no more data from the websocket after disconnecting and trying to reconnect. conn_key returns an actual connection key and not an error.

I am attempting to reconnect sockets for multiple reasons.

  1. I want to reconnect every 23 hours so I am not automatically disconnected by Binance due to their 24 hour connection policy.
  2. I am currently developing my program on a home PC. I want to make sure my program works correctly in case my internet goes down. Of course, with the Rest API, I have been able to do so by simply looping the API call request until I'm back online and it is sent.

I made a short looping function which checks for internet connectivity, and ends when it's back up. I would like to end Binance socket(s) prior to this, and start a new socket connection afterwards when I'm back online.

Please do not suggest I get a VPS; that is not a solution, that's a workaround. The solution in question is being able to disconnect and connect to Binance websockets. I don't mean that in a rude way, I would just like to make my program as versatile as possible.

Most helpful comment

I've had the same issue as I couldn't restart any socket that I disconnected. Following the snippet given in the original question

bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()
bm.close()
bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()

The problem with this is that bm.start() was called after it was already started. The BinanceSocketManager is just a manager for sockets. When you start a socket it gets added to the manager and after you add the sockets you want, you can start the manager. When attempting to restart the socket, you only close the sockets but keep the manager is still alive which means you don't need to start it again using bm.start(). So, here is the new code

bm = BinanceSocketManager(client)  # init the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager
bm.start()  # started the manager
bm.close()  # closed the sockets handled by the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager

This way you shouldn't have any problems connecting and reconnecting to a socket

All 17 comments

I've got the same issue, I cannot restart a socket after closing it. It just hangs and there's no error.

Same here - I've been battling with this issue for a month now.

To provide a bit more of context - this is the status of BinanceSocketManager:

before first bm.start():

_

after first bm.start():

_

After bm.stop_socket(conn_key):

I don't receive data from Binance anymore so the connection is severed at some point but still:

_

After bm.close():

_

After reactor.stop():

_

It is interesting to note that quitting python cmd line at this point needs CMD-D + CMD-C which most probably means that a loop is still running.

After setting up a new client and linking the BinanceSocketManager to it:

_

After bm.start():

_

Interesting, Thread-2 is automatically stopped, I can only guess because like the doc states:

"Only one instance of each socket type will be created, i.e. only one BNBBTC Depth socket can be created and there can be both a BNBBTC Depth and a BNBBTC Trade socket open at once."

Will investigate the source code and see where the problem lies. My intuition tells me that the problem lies in reactor's feedback loop actually never stopping.

Any help welcome.

Hey @dingoyabuki and @lambi9891 thanks for the examples, I'll have a look into this and see what we can do.

I'll test it with the current code and the proposed pull request #192

This is a simple example which I have used for a while to reconnect, it closes the particular socket after 3 messages are received and then reconnects.

from binance.client import Client

from binance.websockets import BinanceSocketManager

client = Client("", "")


def process_trade_message(message):
    global count, conn_key
    count = count + 1
    print("got ticker message:{}:{}".format(count, message))
    if count >= 3:
        print('closing socket')
        # use either stop_socket or close, or both
        bm.stop_socket(conn_key)
        bm.close()
        # restarting the socket
        conn_key = bm.start_trade_socket('BNBBTC', process_trade_message)
        # reset the count
        count = 0


bm = BinanceSocketManager(client)
count = 0
conn_key = bm.start_trade_socket('BNBBTC', process_trade_message)

bm.start()

Can you check if that works for you. Does it provide what you need?

I have that problem. After 24-30 hours websocket do not recive any messages.

    bm.stop_socket(conn_key)
    bm.close()
    conn_key = bm.start_trade_socket('BNBBTC', process_trade_message)

This method don't work, becouse thread not restarted.

@sammchardy's example worked for me when copy and pasted as is. Didn't need to stop the reactor as others have suggested.

I had a slightly different issue, but writing it here just in case it helps someone. If running multiplex sockets, you need to close symbol (e.g. 'eosusdt@trade') individually, you can't pass in the entire conn_key to stop_socket(). This at least wasn't obvious to me. When I individually cycled through each pair, ran bm.close() and restarted the multiplex socket, everything worked fine.

I've had the same issue as I couldn't restart any socket that I disconnected. Following the snippet given in the original question

bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()
bm.close()
bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()

The problem with this is that bm.start() was called after it was already started. The BinanceSocketManager is just a manager for sockets. When you start a socket it gets added to the manager and after you add the sockets you want, you can start the manager. When attempting to restart the socket, you only close the sockets but keep the manager is still alive which means you don't need to start it again using bm.start(). So, here is the new code

bm = BinanceSocketManager(client)  # init the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager
bm.start()  # started the manager
bm.close()  # closed the sockets handled by the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager

This way you shouldn't have any problems connecting and reconnecting to a socket

Thanks, all. It worked for me. Here is with a slight modification so it can stop after some time:

from binance.client import Client
from binance.websockets import BinanceSocketManager
import datetime

api_key=''
api_secret=''
client = Client(api_key, api_secret)

def process_message(message):
    datos=message['data']
    print("got ticker message: {}".format(datos['s'])) 
    #
    # Here main code
    #
    if datetime.datetime.now() > stop:
        print('closing socket')
        bm.close()
        bm.start_multiplex_socket(coins_lower, process_message)
        clock_reset()

def clock_reset():
    global stop
    stop = (datetime.datetime.now() + datetime.timedelta(seconds=15)) 

coins_lower=['xlmbtc@trade', 'xrpbtc@trade', 'ethbtc@trade']

clock_reset()
bm = BinanceSocketManager(client)
bm.start_multiplex_socket(coins_lower, process_message)
bm.start()
bm.close()
bm.start_multiplex_socket(coins_lower, process_message)

Thanks to everyone for the help, there are multiple solutions here that work along with explanations as to why.

I tried the solutions given above, but not always these solutions could reconnect. I end up having a cron job that checks for the timestamp of last received data. If it is old, then it kills the script with PID and restarts it.

Indeed, did not work for me either. Implementing the solution of iUmarov:

  1. started a process
  2. if no message in 60 secs
  3. kill the process and start again

Same problem here. The 'kill process' solution is not viable for me as this is run as a thread concurrently with others, within the same python program. Any other solution?

Same problem here. Restart is not reliable, having the process killed and restarted from outside is not feasible (neither is it a proper solution). Does anyone know the cause for this behavior?

I've had the same issue as I couldn't restart any socket that I disconnected. Following the snippet given in the original question

bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()
bm.close()
bm = BinanceSocketManager(client)
conn_key = bm.start_trade_socket('BNBBTC', process_message)
bm.start()

The problem with this is that bm.start() was called after it was already started. The BinanceSocketManager is just a manager for sockets. When you start a socket it gets added to the manager and after you add the sockets you want, you can start the manager. When attempting to restart the socket, you only close the sockets but keep the manager is still alive which means you don't need to start it again using bm.start(). So, here is the new code

bm = BinanceSocketManager(client)  # init the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager
bm.start()  # started the manager
bm.close()  # closed the sockets handled by the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager

This way you shouldn't have any problems connecting and reconnecting to a socket

That doesnt work for me.

I've tried the solution from above:

Any other solutibm = BinanceSocketManager(client)  # init the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket manager
bm.start()  # started the manager
bm.close()  # closed the sockets handled by the manager
bm.start_trade_socket('BNBBTC', process_message)  # start a new socket for the socket managerons? 

It still doesn't work overtime, any other approach for this issue?

Same issue here
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once

It seems like the package is having a lot of problems lately. Not really stable anymore. I tried using the asyncio feature of it and it's a whole mess.

``` # Initializes websocket stream
def start_websocket(self):
# Clean and prepare list of pairs for socket stream
crypto = [f"{trading_pair.lower()}@kline_{self.interval}" for trading_pair in self.pair_list]
# Streams pairs sent in list
# Contains callback to handle data after each request
self.connection_key = self.user_socket.start_multiplex_socket(crypto, self.socket_manager)
# Start web socket
self.user_socket.start()

# Initializes websocket stream
def stop_websocket(self):
    # Stop web socket
    self.user_socket.stop_socket(self.user_socket)```

Same issue here. Price does not update after about 2 hours on my end. It just keeps showing the old values.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

echel0n picture echel0n  路  4Comments

bilgecetin picture bilgecetin  路  6Comments

DaniZz picture DaniZz  路  3Comments

alexandre-a picture alexandre-a  路  4Comments

scalpounet picture scalpounet  路  6Comments