我正在尝试在python中使用协议缓冲区从一台计算机向另一台计算机发送消息。我从一些在线示例中了解到,并尝试用它们做出最小的例子。但是,在我的代码中,服务器不会打印出客户端发送的变量的正确值。非常感谢任何帮助。
首先,test_msg.proto如下:
message test_msg {
required int32 param1 = 1;
required int32 param2 = 2;
}
其次,客户端代码(test_client.py)
from test_msg_pb2 import test_msg
import socket
import sys
import struct
address = ('localhost', 6005)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.connect(address)
data = test_msg()
num_retransmits = 0
while(num_retransmits < 10): # send the same message 10 times
num_retransmits = num_retransmits + 1
data.param1 = 100
data.param2 = 5
s = data.SerializeToString()
totallen = 4 + len(s)
pack1 = struct.pack('>I', totallen) # the first part of the message is length
client_socket.sendall(pack1 + s)
print "[client] param1: ", data.param1, " param2: ", data.param2
第三,服务器代码(test_server.py)
from test_msg_pb2 import test_msg
import socket
import sys
import struct
address = ('localhost', 6005)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(address)
while(1):
print "Listening"
totallen = server_socket.recv(4)
totallenRecv = struct.unpack('>I', totallen)[0]
messagelen = totallenRecv - 4
message = server_socket.recv(messagelen)
msg = test_msg()
msg.ParseFromString(message)
print "[server] param1:", msg.param1, "param2:", msg.param2
然后,在启动服务器之后,我执行客户端并打印出以下10行,因为它发送了10次参数
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
[client] param1: 100 param2: 5
但是,在服务器端,它打印出来
Listening
[server] param1: 0 param2: 0
Listening
[server] param1: 0 param2: 0
Listening
[server] param1: 0 param2: 0
Listening
[server] param1: 0 param2: 0
Listening
[server] param1: 0 param2: 0
Listening
因此,解压缩的数字param1和param2不正确,并且它只收到消息的一半时间。非常感谢你的帮助。
答案 0 :(得分:2)
第一条建议:简化。让我们首先看看我们是否能够在没有协议缓冲区的情况下使用:
import socket
import sys
import struct
address = ('localhost', 6005)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.connect(address)
messages = ["foobar", "barbaz", "bazquxfad", "Jimmy Carter"]
for s in messages:
totallen = 4 + len(s)
pack1 = struct.pack('>I', totallen) # the first part of the message is length
client_socket.sendall(s)
import socket
import sys
import struct
address = ('localhost', 6005)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(address)
while True:
print "Listening"
# totallen = server_socket.recv(4)
# totallenRecv = struct.unpack('>I', totallen)[0]
# messagelen = totallenRecv - 4
message = server_socket.recv(1000)
print message
现在,我不是套接字的专家(这可能是我回答过他们的第一个问题),但是如果你运行这个例子,你会获得预期的输出。这告诉我的是每个发送对应一个.recv
。据推测,sockets
库正在处理 length 的详细信息。当然,在接收方面,很可能你希望知道长度,以便你可以通过一个合适的maxlen。如果是这种情况,那么我认为您可能需要发送2条消息。第一条消息的长度为4,为整数长度。第二条消息应该有数据。 e.g:
import socket
import sys
import struct
address = ('localhost', 6005)
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.connect(address)
messages = ["foobar", "barbaz", "bazquxfad", "Jimmy Carter"]
for s in messages:
totallen = len(s)
pack1 = struct.pack('>I', totallen) # the first part of the message is length
client_socket.sendall(pack1)
client_socket.sendall(s)
import socket
import sys
import struct
address = ('localhost', 6005)
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_socket.bind(address)
while True:
print "Listening"
totallen = server_socket.recv(4)
totallenRecv = struct.unpack('>I', totallen)[0]
message = server_socket.recv(totallenRecv)
print message
现在序列化应该很简单。毕竟,proto缓冲区序列化为字符串就好了。
答案 1 :(得分:1)