Python 支持二进制文件的Tornado websockets第2部分

Python 支持二进制文件的Tornado websockets第2部分,python,websocket,tornado,Python,Websocket,Tornado,我试图通过WebSocket传递二进制数据,更确切地说,是通过WebSocket传递压缩字符串。在我当前的设置中,我使用tornado作为服务器,客户端传输二进制数据。二进制数据是通过使用zlib压缩数据形成的。客户端和服务器都非常简单,如下所示 服务器: import tornado.websocket import tornado.httpserver import tornado.ioloop import tornado.web class WebSocketServer(tornad

我试图通过WebSocket传递二进制数据,更确切地说,是通过WebSocket传递压缩字符串。在我当前的设置中,我使用tornado作为服务器,客户端传输二进制数据。二进制数据是通过使用
zlib
压缩数据形成的。客户端和服务器都非常简单,如下所示

服务器:

import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web

class WebSocketServer(tornado.websocket.WebSocketHandler):
    def open(self):
        print 'OPEN'

    def on_message(self, message):
        print 'len = {}'.format(len(message))
        print 'GOT MESSAGE: {}'.format(message.decode('zlib'))

    def on_close(self):
        print 'CLOSE'

app = tornado.web.Application([
        (r'/', WebSocketServer)
    ])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.web

class WebSocketServer(tornado.websocket.WebSocketHandler):
    def open(self):
        print 'OPEN'

    def on_message(self, message):
        print 'len = {}'.format(len(message))
        print 'GOT MESSAGE: {}'.format(message)
        self.write_message(message.encode('zlib'))

    def on_close(self):
        print 'CLOSE'

app = tornado.web.Application([
        (r'/', WebSocketServer)
    ])
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(9500)
tornado.ioloop.IOLoop.instance().start()
客户:

import websocket

host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
message = 'this is my message'.encode('zlib')
print 'Length of message is {}'.format(len(message))
ws.send(message)
import websocket

host = 'localhost'
port_ws = 9500
ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
#message = 'this is my message'.encode('zlib')
message = 'this is my message'
print 'Length of message is {}'.format(len(message))
ws.send(message)
assert ws.recv().decode('zlib') == message
客户端不会抛出任何错误,它会打印出消息:
消息长度为24
。根据zlib标准,消息编码为
str
。另一端的服务器没有显示它收到了任何消息,它只知道客户端已经连接,然后断开了连接。有人知道问题出在哪里吗?我不确定问题出在tornado还是websockets库中。有什么建议吗


编辑:为了回应下面的评论(@plg),我修改了上面的脚本以显示:

  • 非编码消息可以从客户端发送到tornado服务器
  • Tornado可以用编码的信息进行回复
  • 服务器:

    import tornado.websocket
    import tornado.httpserver
    import tornado.ioloop
    import tornado.web
    
    class WebSocketServer(tornado.websocket.WebSocketHandler):
        def open(self):
            print 'OPEN'
    
        def on_message(self, message):
            print 'len = {}'.format(len(message))
            print 'GOT MESSAGE: {}'.format(message.decode('zlib'))
    
        def on_close(self):
            print 'CLOSE'
    
    app = tornado.web.Application([
            (r'/', WebSocketServer)
        ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(9500)
    tornado.ioloop.IOLoop.instance().start()
    
    import tornado.websocket
    import tornado.httpserver
    import tornado.ioloop
    import tornado.web
    
    class WebSocketServer(tornado.websocket.WebSocketHandler):
        def open(self):
            print 'OPEN'
    
        def on_message(self, message):
            print 'len = {}'.format(len(message))
            print 'GOT MESSAGE: {}'.format(message)
            self.write_message(message.encode('zlib'))
    
        def on_close(self):
            print 'CLOSE'
    
    app = tornado.web.Application([
            (r'/', WebSocketServer)
        ])
    http_server = tornado.httpserver.HTTPServer(app)
    http_server.listen(9500)
    tornado.ioloop.IOLoop.instance().start()
    
    客户:

    import websocket
    
    host = 'localhost'
    port_ws = 9500
    ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
    message = 'this is my message'.encode('zlib')
    print 'Length of message is {}'.format(len(message))
    ws.send(message)
    
    import websocket
    
    host = 'localhost'
    port_ws = 9500
    ws = websocket.create_connection('ws://{}:{}/'.format(host, port_ws))
    #message = 'this is my message'.encode('zlib')
    message = 'this is my message'
    print 'Length of message is {}'.format(len(message))
    ws.send(message)
    assert ws.recv().decode('zlib') == message
    
    这个系统运行得很好。断言不会抛出错误。解码后的消息与发送消息匹配。所以我想这两种方法都有问题:

  • 从客户端发送编码消息
  • 龙卷风接收编码信息
  • 老实说,我相信第一种选择比龙卷风更有可能。在我看来,如果传入的消息没有按照websocket标准正确解码,我相信tornado会提醒我。还有什么建议吗


    编辑:更多关于谁有错的发展。我没有使用自己的服务器来中继回连接,而是将连接中继到
    ws://echo.websocket.org/
    。我的测试应用程序如下所示:

    import websocket
    
    host = 'localhost'
    port_ws = 9500
    ws = websocket.create_connection('ws://echo.websocket.org/')
    message = 'this is my message'
    ws.send(message.encode('zlib'))
    got = ws.recv().decode('zlib')
    print 'GOT: {}'.format(got)
    assert got == message
    

    这实际上通过了测试,数据接收得很好。所以我猜tornado接收数据时有什么问题?

    在查看了
    websocket
    库的源代码后,我发现默认情况下,它将数据包格式化为文本。通过更改行:

    ws.send('message')
    # to:
    ws.send('message', opcode=websocket.ABNF.OPCODE_BINARY)
    # or better yet:
    ws.send_binary('message')
    

    包裹会很好地发送过来。Tornado我猜只是忽略了伪二进制数据包,因为它们被标记为文本并包含二进制。

    多亏了Tornado支持websocket压缩扩展

    您是否尝试过以另一种方式执行,以查看它是否有效或是否引发异常?在客户端和open()中使用ws.recv():self.write_message('this is my message')。encode('zlib')。另外,您是否尝试过不使用zlib压缩,以防我们丢失了一些东西。@plg它的工作方式正好相反。我向tornado发送了一条标准ascii消息,tornado用编码的消息进行了回复。所以这个方向是可行的。