簡體   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