python gevent websocket客户端获取错误“;解码错误:被截断的消息;用于回显协议缓冲区消息

python gevent websocket客户端获取错误“;解码错误:被截断的消息;用于回显协议缓冲区消息,python,websocket,protocol-buffers,gevent,Python,Websocket,Protocol Buffers,Gevent,我有一个简单的websocket服务器,它将所有消息回显到客户端 import gevent from geventwebsocket.resource import WebSocketApplication from geventwebsocket.server import WebSocketServer from geventwebsocket.resource import Resource import ams_pb2 class AMSWebSocketServer(WebSock

我有一个简单的websocket服务器,它将所有消息回显到客户端

import gevent
from geventwebsocket.resource import WebSocketApplication
from geventwebsocket.server import WebSocketServer
from geventwebsocket.resource import Resource
import ams_pb2

class AMSWebSocketServer(WebSocketApplication):
    def __init__(self, ws):
        super(AMSWebSocketServer, self).__init__(ws)
        pass

    def on_open(self):
        pass

    def on_message(self, message):
        print 'received message'
        print message
        if message is None:
            print 'message none'
            return

        print 'echo message back'
        self.ws.send(message)

    def on_close(self, reason):
        print "connection closed"
        gevent.sleep(0)


resource = Resource({'/': AMSWebSocketServer})
服务器是使用gunicorn命令生成的

gunicorn -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" -b 127.0.0.1:9000 gunicorn_test:resource
我有一个测试客户机,它发送websocket消息以进行回显

from ws4py.client.threadedclient import WebSocketClient
import ams_pb2


class DummySwitch(WebSocketClient):
    def closed(self, code, reason=None):
        pass

    def received_message(self, msg):
        if msg is None:
            print 'none'
            return
        print 'received message'
        ams_message = ams_pb2.AMSConfig()
        ams_message.ParseFromString(msg)
        print ams_message
        print msg


if __name__ == '__main__':
    end_point = 'ws://127.0.0.1:9000'

    client = DummySwitch(
        end_point,
        headers=[
        ]
    )
    client.connect()

    print 'sending message'

    AMSConfig = ams_pb2.AMSConfig()
    AMSConfig.CliConfig = True
    print AMSConfig
    msg = AMSConfig.SerializeToString()

    #msg = 'Hello'
    print msg

    client.send(msg)

    client.run_forever()
我的protobuff文件是: 成套医疗辅助系统

message AMSConfig {
  optional bool CliConfig = 1;
}
每当我的客户端向服务器发送protobuff消息时,我都可以看到它在服务器中被解析,但是当服务器向客户端回显相同的消息时,客户端失败,原因是:

文件“client_test.py”,第15行,在收到的_消息中 ams_message.ParseFromString(msg) 文件“/usr/lib/python2.6/site packages/google/protobuf/message.py”,第186行,格式为ParseFromString self.MergeFromString(序列化) 文件“/usr/lib/python2.6/site packages/google/protobuf/internal/python_message.py”,第847行,位于MergeFromString中 引发消息\u mod.DecodeError('被截断的消息') 解码错误:消息被截断

因此,我修改了代码以发送一个简单的字符串,并且我看到发送到服务器的“Hello”字符串正在被回显,客户端能够打印消息。但是,客户端无法解析回显的protobuff消息

我无法理解为什么字符串的回显有效,但在我的示例中,协议缓冲区的回显无效


谢谢你的帮助

我在客户端遇到了同样的问题,但这可以通过在客户端代码中增大接收缓冲区的大小来解决。例如:

maxpkglen = 1024 * 1024 // original maxpkglen = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(req, (server, port))
rsp, server = s.recvfrom(maxpkglen)
s.close()

在我的客户机程序中也会遇到类似的问题,因为我将接收缓冲区设置为硬数字1024。当我把接收缓冲区的大小扩大到10*1024时,它就解决了。也谢谢@lulyon的提示


您可能需要一个循环来读取对等代码中的所有数据

我有这个问题,但对我来说,答案不是直接从
接收的消息(self,msg)
中使用
msg
变量,而是使用
msg.data
来实际获取与消息相关联的数据并从中进行解析。

消息内容不知何故被破坏了。也许您可以在发送消息之前打印出消息的base64,也可以打印您返回的消息的base64,并进行比较?这样可能会更清楚出了什么问题。一种可能性是,内容在某处被解释为text/unicode,这将导致损坏,因为它实际上是二进制数据。问题是在客户端,我需要将接收到的对象转换为str。在使用msg之前,我缺少isinstance(msg,str),这导致客户端代码无法解析代码的问题。