[英]Sending Protocol Buffer encoded message from Python Server to Java Client
我正在編寫一個使用協議緩沖區來編碼一些數據的小服務器。
Android Client 和 Python Server 之間打開 TCP Socket
Android 客戶端發送字符串以作為普通換行符分隔的 utf-8 進行處理。
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)
這就是我被困的地方...
# 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.