java - 数据包 : Effectively representing different packet types

标签 java android c++ sockets multiplayer

我正在尝试设计一个服务器/客户端架构,我想请教你们以确定表示和解析不同类型数据包的最佳方式。需要对每种数据包类型进行不同的解析。下面代表我会看到的数据包类型。

[*packet_type*][length][variable length data]
*packet_type* describes the type of packet we're sending (client login, server returning authentication, data, etc)
length describes how much data to read
variable length data contains the info to be sent. it will be specialized based on the packet_type. the data will be variable regardless of 

我调查了 tcphdr struct,我想我可以使用类似类型的 header 来表示 *packet_type* 和长度。然后,我将使用字符串来表示数据。

public class Packet {
    public enum PKT_TYPE {
            CL_REGISTER,
            CL_LOGIN,
            SRV_AUTH,
            SRV_GAME_INFO,
    }

    PKT_TYPE _packet_type;
    int _length;
    String _data;
}

现在有了一个共同的基础,我想我可以为每个 *packet_type* 实现类和发送/接收方法。但是,我觉得这不是很可扩展,而且很难维护。一个(粗略的,伪的)例子是

public class Packet {
...
   public class Pkt_CL_LOGIN extends Packet {
       String _loginname;
       String _password;

       public boolean send() {
           //socket.write(CL_LOGIN, length, _loginname+_password);
       }
       public Pkt_CL_LOGIN parse(String data) {
           //removed header already, so first byte will be data
           //extract login + password
           _loginname = login;
           _password = password;
           return this;
       }
   }
   public Packet receive() {
       //read from socket
       //parse header for packet_type
       switch (packet_type)
           case CL_LOGIN:
               return (new Pkt_CL_LOGIN()).parse(data);
   }
}

谁能给我一些关于如何以不同方式实现的建议?我不太确定是否有,但也许有更多经验的人可以给我一些见解(例如他们如何在多人游戏中做到这一点等)

谢谢!

最佳答案

我目前正在使用 Protocol Buffers 制作多线程 C++ 聊天服务器用于实际的协议(protocol)实现。重点是,我认为你应该使用它们:它们为你需要的每个数据包提供了一个漂亮的接口(interface),它们可以用于多种语言(C++、Java 和 Python 只是开始,我认为它们有一些 Ruby 接口(interface)作为好吧)并且它们允许您毫不费力地创建通用协议(protocol),因为它们消除了序列化问题以及为每个数据包编写自己的类的需要。此外,还有针对移动设备的特定“精简版”版本(如果您正在为 Android 编写代码,它可能会派上用场)。

关于数据包,我知道有两种方法可以跟踪数据包何时结束:第一种是固定长度的数据包,第二种是在实际发送数据包之前发送长度。这同样适用于数据包类型。如果你没有很多数据包类型,你可以只使用一个 unsigned char (现在,这是 C++,但我想应该有一些方法可以在 Java 中做同样的事情)来表示它会为您提供恰好 255 种数据包类型(如果您问我,则多于所需)。

在我的服务器中,我实际上解决了发送一个包含数据包长度和类型(都是固定长度 uint32)的固定长度 header 的问题,然后对其进行解析,然后再次读取套接字以检索信息,然后相应地解析并发送到客户端处理程序中的适当处理程序。我认为这种方法非常好,除了......我正在使用一些额外的内存(数据包类型太大)......

作为 Protocol Buffer 的示例,您的 .proto 文件可能看起来像这样:

message Header {
    required fixed32 length = 1;
    required fixed32 type = 2; // Note: don't use an enum here, as the values are serialized to varint, which simply kills your fixedness.
}

message Login {
    required string nickname = 1;
    required string password = 2;
}

enum ErrorType {
    BAD_HEADER = 0;
    WRONG_PASSWORD = 1;
}

message Error {
    required ErrorType type = 1;
    optional string message = 2;
}

关于java - 数据包 : Effectively representing different packet types,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9247150/

相关文章:

java - 如何在不同位置使用 LinearLayout 两次?中心和底部

c++ - 同时需要 typedef 和 class

java - 高级多线程 - Java

Java:打印数组:IndexOutOfBoundsException:索引:2,大小:2

android - 带有 simple_list_item_single_choice 的文本颜色数组适配器

android - 在 Android 应用程序中共享照片时,Facebook "Share"按钮被禁用

c# - Protobuf-net 上使用嵌套数据反序列化的无效线类型异常(C++ 到 C#)

c++ - std::once_flag 相当于 BOOST_ONCE_INIT

java - 如何转换 Java Web 应用程序以在 Google App Engine 上部署

java - 如何使用 Ajax Paging Navigator 发送到顶部