Anjanish
Anjanish

Reputation: 11

python gevent websocket client getting error "DecodeError: Truncated message" for echoed back protocol buffer message

I have simple websocket server, which echoes all the message back to the client.

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})

The server is spawned using gunicorn command

gunicorn -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" -b 127.0.0.1:9000 gunicorn_test:resource

I have a test client, which sends the websocket message to be echoed back

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()

My protobuff file is : package ams;

message AMSConfig {
  optional bool CliConfig = 1;
}

Whenever my client send a protobuff message to the server, i am able to see it getting parsed in the server, but when the server echoes back the same message to the client, the client fails due to:

File "client_test.py", line 15, in received_message ams_message.ParseFromString(msg) File "/usr/lib/python2.6/site-packages/google/protobuf/message.py", line 186, in ParseFromString self.MergeFromString(serialized) File "/usr/lib/python2.6/site-packages/google/protobuf/internal/python_message.py", line 847, in MergeFromString raise message_mod.DecodeError('Truncated message.') DecodeError: Truncated message.

So, i modified the code to send a simple string and i see that the 'Hello' string being sent to the server is being echoed back and client is able to print the message. But, the client fails to parse protobuff message echoed back.

I am unable to understand why the echo back for a string works but for a protocol buffer it doesn't work in my example.

Thanks for help.

Upvotes: 1

Views: 4341

Answers (3)

Joe Staines
Joe Staines

Reputation: 321

I had this problem but for me the answer was to not use the msg variable directly from the received_message(self, msg), but rather use msg.data to actually get the data associated with the message and parse from that.

Upvotes: 0

Simon Jin
Simon Jin

Reputation: 137

i also encounter problem like this in my client program, because i set the receiving buffer to a hard number 1024. and when i enlarge the receiving buffer size to 10*1024, it is solved. also thanks for @lulyon 's tip.

you may need a loop for reading all the data from the peer code!

Upvotes: 0

lulyon
lulyon

Reputation: 7265

I encounter same problem on client side, but this might be solved by enlarge receiving buffer size in client side code. For example:

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()

Upvotes: 1

Related Questions