【问题标题】:Java: how to describe a network packet?Java:如何描述一个网络数据包?
【发布时间】:2012-07-25 14:36:08
【问题描述】:

我是 Java 新手,正在编写一个通过 UDP/TCP 使用自己的网络协议的程序。 C中有这样一个包:

struct test_package {
    u32 cmd;
    u32 args;
    u32 flags;
};

以UDP为例,我从DatagramPacket中得到的是字节数据[]。如何将其转换为包结构?

如果在 C 中,如果没有对齐限制,它只是 (struct test_package *)data

谢谢

【问题讨论】:

  • 您需要注意,将 C 结构直接放在线路上是非常糟糕的工程。它引入了对编译器的依赖关系、编译器版本、生效的#pragmas、编译当天使用的编译器选项……不推荐。您必须定义一个网络字节协议并用您的编程语言编写您必须编写的任何内容才能正确实现它。正确执行该操作时 Java 假定的低效率与错误执行时 C 的明显效率无法相提并论。

标签: java networking


【解决方案1】:

假设你有一堂课:

public class TestPackage implements Serializable
{
   long cmd;
   long args;
   long flags;
}

您可以通过序列化将其作为字节[] 存储在 DatagramPacket 中。然后在另一端,您可以获取 byte[] 并将其反序列化回 TestPackage 的确切实例。

(这是序列化/反序列化的样子)

public static byte[] serialize(Object object) {
   ByteArrayOutputStream out = new ByteArrayOutputStream();
   ObjectOutputStream oos = new ObjectOutputStream(out);
   oos.writeObject(object);
   return out.toByteArray();
}

public static Object deserialize(byte[] datagramData) {
   ByteArrayInputStream in = new ByteArrayInputStream(datagramData);
   ObjectInputStream ois = new ObjectInputStream(in);
   return ois.readObject();
}

【讨论】:

  • 这会起作用,但它假定两端都在运行基于 Java 的客户端。
  • 它看起来像是一种通用的序列化/反序列化方式。但是能保证byte[]的数据布局和struct test_package一样吗?
  • @user1550330 不,布局不会是一样的,就像 casablanca 说的那样,它假设另一端也是 Java 并且您正在传递 Classes 并且第四。
【解决方案2】:

Java 不提供直接内存访问,因此不能像在 C 中那样将其强制转换为结构。您必须自己解析字节数组,例如:

byte data[] = ...;
DataInput input = new DataInputStream(new ByteArrayInputStream(data));

int cmd = input.readInt();
int args = input.readInt();
int flags = input.readInt();

【讨论】:

  • 看起来我必须为每种包实现这样的代码。它看起来有点多余,我必须这样做。而且我不确定拥有这样的内存副本如何保持效率。
  • @user1550330:是的,这有点多余,但 Java 确实适用于面向对象的代码,而不是像这样的低级数据。如果您还关心效率,那么 Java 可能不是正确的解决方案。
猜你喜欢
  • 2012-10-18
  • 2010-09-23
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多