tornado.websocket can not establish a websocket connection

sample code

from tornado.websocket import websocket_connect

from tornado.ioloop import IOLoop

ioloop = IOLoop.instance()

ioloop.add_callback(websocket_connect, url=f'ws://{hostname}:15000/WebSocket')

ioloop.start() # Oops, StreamCloseError("Stream is closed")

Best Answer

  • Jirapongse
    Jirapongse admin
    Answer ✓

    @gxu

    I found a workaround of this issue at https://github.com/tornadoweb/tornado/issues/2207.

    The code is:

    from tornado.websocket import websocket_connect
    from tornado import httpclient
    from tornado import httputil
    from tornado.ioloop import IOLoop

    def new_missing(self, key):
    if key == 'Sec-WebSocket-Protocol':
    normalized = 'Sec-WebSocket-Protocol'
    elif key == 'Sec-WebSocket-Key':
    normalized = 'Sec-WebSocket-Key'
    elif key == 'Sec-WebSocket-Version':
    normalized = 'Sec-WebSocket-Version'
    else: normalized = "-".join([w.capitalize() for w in key.split("-")])
    self[key] = normalized
    self.queue.append(key)
    if len(self.queue) > self.size:
    old_key = self.queue.popleft()
    del self[old_key]
    return normalized

    httputil._NormalizedHeaderCache.__missing__ = new_missing

    ioloop = IOLoop.instance()
    ioloop.add_callback(websocket_connect, url='ws://host:15000/WebSocket', subprotocols=["tr_json2"],)
    ioloop.start() # Oops, StreamCloseError("Stream is closed")

Answers

  • Hi @gxu,

    I don't believe we have examples using tornado.websocket but what I would try first is to ensure you can properly communicate with one of the many examples we have outlined within the documentation. Depending on the language, you can try one that is appropriate for your environment. If you are unable to properly communicate, this may be a result of issues with connectivity within your own environment - it may be going through a proxy. Or the server you are connecting is either an older version of ADS (<3.2) or has not been enabled. You will need to contact your market data specialist managing your servers.

    If you are successful with the example, then you will need to review the example code to ensure you are not missing any steps. For example, I don't see anywhere within your code where you specified the "tr_json2" protocol. For example, in .NET, when you create a WebSocket connection, you need to specify the protocol as:

    ws = new WebSocket(url, "tr_json2");

    For tornado.websocket, you will need to understand where to specify this.

    Hope this helps.

  • yes i can connect it using the existing example. Our trep is update to date.

  • Hi @gxu,

    Great that the example works. From here, you will need to review the working examples to ensure you are executing all the steps necessary - for example, the protocol reference I mentioned in my answer above.

  • researched a lot with tonado.websocket, with the code, it still fail immediately.

    from tornado.websocket import websocket_connect

    from tornado.ioloop import IOLoop

    ioloop = IOLoop.instance()

    ioloop.add_callback(websocket_connect, url=url, subportocols=['tr_json2'])

    ioloop.start() # Oops, StreamCloseError("Stream is closed")

  • Hi @gxu,

    I have not used this WebSocket implementation before so unfortunately I can't provide much help here. What we do know is that your server is set up properly as you were able to get other examples to work. If you have not used the Tornado WebSocket client software before, I would research how to setup a client/server test to at least ensure you are using their implementation correctly.

  • @gxu

    I have used Wireshark to capture the network packets sent by tornado.websocket. The TCP payload shows that tornado.websocket uses the following headers (Sec-Websocket-Key, Sec-Websocket-Version, and Sec-Websocket-Protocol) in the HTTP headers.

    image

    From my test, TREP expects the following headers (Sec-WebSocket-Key, Sec-WebSocket-Version, and Sec-WebSocket-Protocol) with a capital letter of S in Socket. It seems that TREP uses case sensitive for the HTTP headers.

    I can replicate the issue with curl command. The following command doesn't work.

    curl --no-buffer --header "Upgrade: websocket"  --header "Connection: Upgrade"   --header "Sec-Websocket-Key: s595Nk+O22u2vOpCFHFAqQ==" --header "Sec-Websocket-Version: 13" --header "Sec-Websocket-Protocol: tr_json2" --header "Accept:"  --header "User-Agent:" --header "Host:" http://192.168.27.91:15000/WebSocket

    However, the below command with a capital letter of S in Socket works.

    curl --no-buffer --header "Upgrade: websocket"  --header "Connection: Upgrade"   --header "Sec-WebSocket-Key: s595Nk+O22u2vOpCFHFAqQ==" --header "Sec-WebSocket-Version: 13" --header "Sec-WebSocket-Protocol: tr_json2" --header "Accept:"  --header "User-Agent:" --header "Host:" http://192.168.27.91:15000/WebSocket

    You should contact TREP support team MyRefinitiv Get Support to verify this behaviour.

  • Thank you it works like a charm. However according to https://github.com/tornadoweb/tornado/issues/2207 this seems that the root cause is that infinitiv websocket server does not exactly follow either http1 and http2 standard. Could it be fixed in future release?

  • problem resolved with jirapongse.phuriphanvichai's suggestion. The issue is raised to TREP support. this thread should be closed

  • the issue was raised to TREP support team. Close this thread