Python 为什么我的Protobuf消息只有在从Windows设备发送到Linux设备时才会被截断?

Python 为什么我的Protobuf消息只有在从Windows设备发送到Linux设备时才会被截断?,python,linux,windows,ubuntu,protocol-buffers,Python,Linux,Windows,Ubuntu,Protocol Buffers,我正在使用一个简单、简化、同步的Python服务器和客户端组合,通过TCP连接发送Google Protobuf消息。服务器运行在Windows XP上,使用Python 2.5.4和Google Protobuf 2.4.1。客户端运行在Ubuntu 12.04服务器上,使用Python 2.7.3和Google Protobuf 2.4.1 当我在XP机器上运行服务器并尝试使用Ubuntu机器上的客户机与之对话时,服务器解析请求消息的方式很好,发送响应消息的方式也很好,但是客户机遇到了一个g

我正在使用一个简单、简化、同步的Python服务器和客户端组合,通过TCP连接发送Google Protobuf消息。服务器运行在Windows XP上,使用Python 2.5.4和Google Protobuf 2.4.1。客户端运行在Ubuntu 12.04服务器上,使用Python 2.7.3和Google Protobuf 2.4.1

当我在XP机器上运行服务器并尝试使用Ubuntu机器上的客户机与之对话时,服务器解析请求消息的方式很好,发送响应消息的方式也很好,但是客户机遇到了一个
google.protobuf.message.DecodeError:Truncated message
错误

如果我在XP机器上同时运行客户端和服务器,我不会遇到错误,如果我在Ubuntu机器上运行服务器,在XP机器上运行客户端,我也不会遇到错误

似乎它可能与实际的Protobuf消息本身有关。。。如果我使用一个非常简单的Protobuf消息,比如下面的例子中的消息,事情似乎很好。然而,一旦我开始使用我们在生产中使用的实际Protobuf消息,我就会看到错误。尽管如此,当服务器在Windows上,客户端在Ubuntu上时,我只得到了错误,这看起来还是很奇怪

知道会发生什么吗?!考虑到一些环境限制,我必须在Windows机器上使用Python 2.5和Google Protobuf 2.4.1

示例protobuf.proto

message Foo {
  required string name = 1;
}

message Bar {
  required string name = 1;
}

message Sucka {
  required string name = 1;
  repeated Foo    foos = 2;
  repeated Bar    bars = 3;
}

message Result {
  enum Exception {
    NONE    = 0;
    GENERIC = 1;
  }

  required Exception exception = 1;
  optional string    message   = 2;
  optional Sucka     sucka     = 3;
}
server.py

import signal, socket, struct

from protobuf import Sucka, Result

class TestServer():
  def __init__(self, host = '0.0.0.0', port = 9989):
    self.host = host
    self.port = port

    self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.socket.bind((self.host, self.port))
    self.socket.listen(1)

    self.running = False
    self.conn    = None

    self.run()

  def run(self):
    def handle_exit(signum, stack):
      print 'Shutting down server in response to signal %s' % (str(signum))
      self.running = False

    signal.signal(signal.SIGINT,  handle_exit)
    signal.signal(signal.SIGTERM, handle_exit)

    print 'Waiting on a connection'
    self.running = True

    while self.running:
      try:
        self.conn, addr = self.socket.accept()

        print 'Connection from:', addr

        size_t = self.conn.recv(4)
        size   = struct.unpack('!I', size_t)
        data   = self.conn.recv(size[0])

        if not data:
          raise Exception('No data... did the client close the connection?')

        result = Result()

        try:
          sucka = Sucka()
          sucka.ParseFromString(data)

          result.exception = result.NONE
          result.sucka.CopyFrom(sucka)
        except Exception, ex:
          print str(ex)
          result.exception = result.GENERIC
          result.message   = 'Exception: %s' % (str(ex))
        finally:
          if self.conn: self.conn.close()

    self.socket.close()

if __name__ == '__main__':
  s = TestServer()
client.py

import socket, struct, time

from protobuf import Sucka, Result

class TestClient():
  def __init__(self, sucka, host = '127.0.0.1', port = 9989):
    self.addr = (host, port)
    self.__call(sucka)

  def __call(self, sucka):
    size   = sucka.ByteSize()
    size_t = struct.pack('!I', size)

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    sock.connect(self.addr)
    sock.send(size_t)
    sock.send(sucka.SerializeToString())

    size_t = sock.recv(4)
    size   = struct.unpack('!I', size_t)
    data   = sock.recv(size[0])

    result = Result()
    result.ParseFromString(data)

    if result.exception != Result.NONE:
      raise Exception(result.message)

    print str(result.sucka)

if __name__ == '__main__':
  import sys, os
  sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))

  from protobuf import Sucka

  sucka      = Sucka()
  sucka.name = 'testing'

  for i in range(0, 25):
    foo      = sucka.foos.add()
    foo.name = 'foo-%i-tester' % i

  for i in range(0, 25):
    bar      = sucka.bars.add()
    bar.name = 'bar-%i-tester' % i

  c = TestClient(sucka, '127.0.0.1', 9989)

在python中,
conn.recv
是否准确读取了那么多字节?(很抱歉,我不是python爱好者,但错误的套接字读取是这里的常见原因)-还有-您是否记录了发送的内容和到达的内容,并对它们进行了比较?
conn.recv
只接收给定数量的字节-它可能接收较少的字节,在这种情况下,您需要再次调用
recv
,以接收更多字节。我想这就是问题所在——您可以通过添加一些打印语句来验证,以了解每端实际发送和接收的字节数。多亏了你们两位。它确实与recv有关。我添加了一个
while循环
,以保持
recv
ing,直到收到的数据长度与预期相符。如果你们中有人想对这个问题给出一个真实的答案,我会接受的。