I am trying to connect to Cryptocompare's websocket stream using socketIO from a Python client. This is proving to be challenging. Here is some sample Python code:
from socketIO_client import SocketIO
print "connecting to server"
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket'])
print "Connected"
However, I am not able to connect, whatever I do. In fact, this is the result of that connect
connecting to server
Traceback (most recent call last):
File "test.py", line 4, in <module>
socketIO = SocketIO('https://streamer.cryptocompare.com/',443, transports=['websocket'])
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 353, in __init__
resource, hurry_interval_in_seconds, **kw)
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 54, in __init__
self._transport
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 62, in _transport
self._engineIO_session = self._get_engineIO_session()
File "/usr/local/lib/python2.7/site-packages/socketIO_client/__init__.py", line 76, in _get_engineIO_session
transport.recv_packet())
StopIteration
Wrapping the above code in a try-catch and printing the exception yields no extra information. Any help would be greatly appreciated.
Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket for transport when possible, it adds additional metadata to each packet.
Socket.IO was created in 2010. It was developed to use open connections to facilitate realtime communication, still a relatively new phenomenon at the time. Socket.IO allows bi-directional communication between client and server.
js) and the Socket.IO client (browser, Node. js, or another programming language) is established with a WebSocket connection whenever possible, and will use HTTP long-polling as fallback.
The socketIO_client library does not seem to support the XHR polling protocol that is used by cryptocompare. I got it to work by overriding the method recv_packet
in the socketIO_client.transports.XHR_PollingTransport
class.
import logging
import socketIO_client
from socketIO_client.transports import get_response
from socketIO_client.parsers import get_byte, _read_packet_text, parse_packet_text
from requests.exceptions import ConnectionError
# extra function to support XHR1 style protocol
def _new_read_packet_length(content, content_index):
packet_length_string = ''
while get_byte(content, content_index) != ord(':'):
byte = get_byte(content, content_index)
packet_length_string += chr(byte)
content_index += 1
content_index += 1
return content_index, int(packet_length_string)
def new_decode_engineIO_content(content):
content_index = 0
content_length = len(content)
while content_index < content_length:
try:
content_index, packet_length = _new_read_packet_length(
content, content_index)
except IndexError:
break
content_index, packet_text = _read_packet_text(
content, content_index, packet_length)
engineIO_packet_type, engineIO_packet_data = parse_packet_text(
packet_text)
yield engineIO_packet_type, engineIO_packet_data
def new_recv_packet(self):
params = dict(self._params)
params['t'] = self._get_timestamp()
response = get_response(
self.http_session.get,
self._http_url,
params=params,
**self._kw_get)
for engineIO_packet in new_decode_engineIO_content(response.content):
engineIO_packet_type, engineIO_packet_data = engineIO_packet
yield engineIO_packet_type, engineIO_packet_data
setattr(socketIO_client.transports.XHR_PollingTransport, 'recv_packet', new_recv_packet)
logging.basicConfig(level=logging.DEBUG)
try:
socket = socketIO_client.SocketIO('https://streamer.cryptocompare.com')
socket.emit('SubAdd', { 'subs': ['0~Kraken~BTC~USD'] });
socket.wait()
except ConnectionError:
print('The server is down. Try again later.')
The solution is heavily based on this github comment: https://github.com/invisibleroads/socketIO-client/issues/129#issuecomment-330058318
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With