我正在使用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