我正在使用Protocol Buffers for Swift(最新來自CocoaPods)和Google官方Java協議緩衝區客戶端(版本2.6.0)在Java服務器(ServerSocket)和Swift iOS應用程序(GCDAsyncSocket)之間傳遞消息。大多數消息(每秒數百次;我將流式音頻作爲浮點數組等等)流動得很好。然而偶爾,客戶端到服務器的消息不會被解析。 Java代碼拋出一個損壞的協議緩衝區消息
com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero)
兩端我發送表示跟隨,則原始的protobuf消息的字節數4個字節的大端整數。在兩端,我收到要跟隨的字節數,阻塞直到我得到那麼多字節,然後嘗試解析。
在Java-> Swift方向上沒有觀察到錯誤,只有Swift-> Java。
絕大多數消息都很好。隨着正在處理的消息數量,問題頻率似乎會增加。
在Java中,每個客戶端都有一個線程正在與之通話,還有一個線程正在監聽它。偵聽器線程將消息從線路中拉出並放入每個客戶端的LinkedBlockingQueues中。通話線程從該客戶端的LinkedBlockingQueue消息中拉取消息,將它們序列化並將它們發送到該客戶端的輸出流。
// Take a messageBuilder, serialize and transmit it
func transmit(messageBuilder: Message_.Builder) {
do {
messageBuilder.src = self.networkID;
let data = try messageBuilder.build().data()
var dataLength = CFSwapInt32HostToBig(UInt32(data.length))
self.socket.writeData(NSData(bytes: &dataLength, length: 4), withTimeout: 1, tag: 0)
self.socket.writeData(data, withTimeout: 1, tag: 0)
} catch let error as NSError {
NSLog("Failed to transmit.")
NSLog(error.localizedDescription)
}
}
Java的接收方:
public void run() {
while (true) {
try {
byte[] lengthField = new byte[4];
try {
ghost.in.readFully(lengthField, 0, 4);
} catch (EOFException e) {
e.printStackTrace();
ghost.shutdown();
return;
}
Integer bytesToRead = ByteBuffer.wrap(lengthField).order(ByteOrder.BIG_ENDIAN).getInt();
byte[] wireMessage = new byte[bytesToRead];
in.readFully(wireMessage, 0, bytesToRead);
HauntMessaging.Message message = HauntMessaging.Message.parseFrom(wireMessage);
// do something with the message
} catch (IOException e) {
e.printStackTrace();
ghost.shutdown();
return;
}
}
}
任何想法?
另一個想法:在Java中的ByteBuffer讀取和Swift中的UInt32之間是否會有簽名問題?我做對了嗎? – closeparen