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

在两端,我发送一个4字节的大端整数,表示要跟踪的字节数,然后是原始protobuf消息。在两端,我接收到要跟踪的字节数,阻塞直到得到这么多字节,然后尝试解析。
在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;
            }
        }
    }

有什么想法吗?

最佳答案

要调试协议缓冲区消息,请执行以下操作:
在Wireshark中捕获数据包
右键单击只包含protobuf消息的packet子部分并复制十六进制流
使用十六进制编辑器将十六进制流保存到文件
protoc ‒‒decode_raw < file并将输出标记和数据与.proto文件中的标记相匹配
由于异常消息Protocol message contained an invalid tag (zero),我怀疑swift未能生成protobuf消息并发送空消息。

10-07 18:54
查看更多