8

我试图通过 websockets 传递二进制数据,更具体地说是通过 websockets 压缩字符串。在我当前的设置中,我使用 tornado 作为服务器,使用websocket客户端传输二进制数据。二进制数据是通过用 压缩数据形成的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 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)

客户端不会抛出任何错误,它会打印出消息:Length of message is 24. str消息按照 zlib 标准编码为 a 。另一端的服务器没有显示它收到任何消息,它只是知道客户端已经连接,然后断开连接。有谁知道问题出在哪里?我不确定问题出在 tornado 还是 websockets 库中。有什么建议么?


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

  1. 非编码消息可以从客户端发送到龙卷风服务器
  2. 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)
        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')
message = 'this is my message'
print 'Length of message is {}'.format(len(message))
ws.send(message)
assert ws.recv().decode('zlib') == message

该系统工作得很好。断言不会引发错误。解码后的消息与发送消息匹配。所以我想有一个问题:

  1. 从客户端发送编码消息
  2. 龙卷风接收编码信息

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


编辑:关于谁有过错的更多发展。我没有使用我自己的服务器来中继我的第四次连接,而是将连接中继到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

这居然通过了测试,数据收到就好了。所以我猜龙卷风接收数据有问题吗?

4

2 回答 2

6

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

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

数据包将被很好地发送。我猜龙卷风只是忽略了伪造的二进制数据包,因为它们被标记为文本并包含二进制文件。

于 2013-09-22T21:54:23.610 回答
0

由于这个提交, tornado 支持 websocket 压缩扩展。

于 2014-08-27T11:25:30.950 回答