繁体   English   中英

将协议缓冲区编码的消息从 Python 服务器发送到 Java 客户端

[英]Sending Protocol Buffer encoded message from Python Server to Java Client

我正在编写一个使用协议缓冲区来编码一些数据的小服务器。

  1. Android Client 和 Python Server 之间打开 TCP Socket

  2. Android 客户端发送字符串以作为普通换行符分隔的 utf-8 进行处理。

  3. Python Server 进行一些处理以生成响应,它给出一个 Int Arrays 数组:[[int]]。 这是在协议缓冲区文件中编码的:

syntax = "proto2";

package tts;

message SentenceContainer {
    repeated Sentence sentence = 1;
}

message Sentence {
    repeated uint32 phonemeSymbol = 1;
}

它被加载到这个结构中并按如下方式发送......

container = ttsSentences_pb2.SentenceContainer()
for sentence in input_sentences:
    phonemes = container.sentence.add()
    # Add all the phonemes to the phoneme list
    phonemes.phonemeSymbol.extend(processor.text_to_sequence(sentence))


payload = container.SerializeToString()
client.send(payload)
  1. Android 客户端接收协议缓冲区编码的消息并尝试解码。

这就是我被困的地方...

# I get the InputStream when the TCP connection is first opened
bufferIn = socket.getInputStream();
TtsSentences.SentenceContainer sentences = TtsSentences.SentenceContainer.parseDelimitedFrom(bufferIn);

收到消息时,客户端收到此异常:

E/TCP: Server Error
    com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
        at com.google.protobuf.CodedInputStream.checkLastTagWas(CodedInputStream.java:164)
        at com.google.protobuf.GeneratedMessageLite.parsePartialDelimitedFrom(GeneratedMessageLite.java:1527)
        at com.google.protobuf.GeneratedMessageLite.parseDelimitedFrom(GeneratedMessageLite.java:1496)
        at com.tensorspeech.tensorflowtts.TtsSentences$SentenceContainer.parseDelimitedFrom(TtsSentences.java:221)
        at com.tensorspeech.tensorflowtts.network.PersistentTcpClient.run(PersistentTcpClient.java:100)
        at com.tensorspeech.tensorflowtts.MainActivity.lambda$onCreate$0$MainActivity(MainActivity.java:71)
        at com.tensorspeech.tensorflowtts.-$$Lambda$MainActivity$NTUE8bAusaoF3UGkWb7-Jt806BY.run(Unknown Source:2)
        at java.lang.Thread.run(Thread.java:919)

我已经知道这个问题是由于协议缓冲区不是自定界引起的,但我不确定我应该如何正确定界它。 我已经尝试添加一个换行符client.send(payload + b'\\n') ,并将 PB 大小(以字节为单位client.send(payload + b'\\n')添加到负载client.send(container.ByteSize().to_bytes(2, 'little') + payload) ,但我不确定如何继续。

很遗憾没有关于如何在 Java 中使用 TCP 套接字上的协议缓冲区的文档......

好的,我解决了这个......

如果您有一个短期连接,套接字关闭将表示有效负载的结束,因此不需要额外的逻辑。

就我而言,我有一个长期连接,因此关闭套接字以表示有效负载结束是行不通的。

使用 Java 客户端和服务器,您可以使用以下方法解决此问题:

MessageLite.writeDelimitedTo(OutputStream)

然后在接收方:

MessageLite.parseDelimitedFrom(InputStream)

够轻松...

但是在 Python API 中,没有writeDelimitedTo()函数。 因此,我们必须重新创建writeDelimitedTo()正在做什么。 幸运的是,这很简单。 它只是在消息的开头添加一个等于有效负载大小的 _VarintBytes!

client, _ = socket.accept()
payload = your_PB_item.SerializeToString()
size = payload.ByteSize()
client.send(_VarintBytes(size) + payload)

然后在 Java 接收方...

bufferIn = socket.getInputStream();
yourPbItem message;

if ((message = yourPbItem.parseDelimitedFrom(bufferIn)) != null) {
    // Do stuff :)
}

这样,您的协议缓冲区库就知道要读取多少字节,然后就不再关心 InputStream,而不是无限期地坐着听。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM