【问题标题】:Send/read Any type in Protobuf (C++)发送/读取 Protobuf (C++) 中的任何类型
【发布时间】:2021-07-18 09:52:13
【问题描述】:

我现在正在编写一个简单的在线游戏,几个玩家可以一起玩,使用一个集中的 UDP 服务器。我使用 Google Protobuf 3 对数据包/消息进行(反)序列化。目前,我无法确定客户端传入数据包的类型。我如何在 C++ 中做到这一点?

在服务器端(Java),我可以使用以下代码实现:

    private Message parseArbitraryPacket(byte[] data) throws InvalidProtocolBufferException {
        Any any = Any.parseFrom(data);

        for (Class<Message> packetType : listeners.keySet())
            if (any.is(packetType))
                return any.unpack(packetType);

        return null;
    }

其中listeners 是一个Map,它将Message 类(例如KeepAlive.class)映射到相应的侦听器(例如KeepAliveListener)。

这就是我将数据包从服务器 (Java) 发送到客户端的方式:

    public boolean sendPacket(InetAddress targetAddr, Message packet) {
        try {
            byte[] data = Any.pack(packet).toByteArray();
            srv.getUdpServer().send(new DatagramPacket(
                    data, data.length, targetAddr, srv.getConfig().getUdpServerPort()));

            return true; // success
        } catch (IOException ex) {
            log.error("Failed to send a {} packet to {}.",
                    packet.getClass().getName(), targetAddr.getHostAddress());
            log.error("Details:", ex);

            return false; // failure
        }
    }

其中srv.getUdpServer()DatagramSocket — 服务器本身。

我现在如何在我的 C++ 客户端中接收 不同 类型的数据包(我知道如何解析特定类型的数据包,例如 KeepAlive,但如果我不知道我收到了什么类型的数据包?)? C++ 中是否还有Any 类型?我找不到它。

P.S.我在 Java 中找到了 Any 类型 here

【问题讨论】:

    标签: c++ serialization network-programming deserialization protocol-buffers


    【解决方案1】:

    在 C++ 端,您可以执行以下操作。

    包括

    #include <google/protobuf/any.pb.h>
    

    还有'Message'对应的头文件。

    google::protobuf::Any any;
        
    any.ParseFromString(/* put your byte[] data here */);
    
    
    Message msg;
    
    
    if (any.UnpackTo(&msg)
    {
        // successfully unpacked to Message type
        // do rest of code here
    }
    else
    {
        std::cerr << "Unknown request type\n";
    }
    

    【讨论】:

    • 使用 Any 有多安全?我目前使用内部带有“one of”的消息包装器,它允许我确定检索数据包类型(因为 Protobuf 似乎在使用此包装器发送的每个数据包中插入数据包类型/案例 ID)。也就是说,具有相同“签名”(在相同索引处包含相同字段类型)的数据包与“one of”是安全的,并且具有多个空数据包甚至是安全的,只要它们具有不同的“one of”大小写.自从我提出这个问题后,我意识到 Any 在这些方面更糟糕,不是吗?
    猜你喜欢
    • 2023-04-01
    • 2011-03-04
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 2017-07-11
    • 1970-01-01
    • 2013-12-03
    相关资源
    最近更新 更多