【问题标题】:UDP packet: How to send different datatypes in one packet?UDP数据包:如何在一个数据包中发送不同的数据类型?
【发布时间】:2017-01-14 09:40:04
【问题描述】:

我正在编写多人游戏,但我很难处理 udp 数据包的大小。我想通过 udp 数据包发送多个敌人的统计数据(hp、位置、id)。这是重要的代码部分:

Byte[] datagramPacketData = ("11" + String.valueOf(entityAmount) + "," + gamename + "," + username + entitiesToBeSent).getBytes();

如您所见,我将所有数据合并为一个字符串,然后在发送之前将其转换为 byte[]。但是 chars 比 little ints(用于 id 和 position)和 longs(hp) 消耗更多的字节。 例如:一个暴徒有 2.000.000 hp。该数字将消耗 7 个字符(=7 个字节),但它只需要 4 个字节。如何在不使用对象流的情况下通过使用更少的字节来发送所有这些数据?

我会很高兴有一些建议! 非常感谢您。

【问题讨论】:

  • 将每个单独的块转换为字节,而不是将它们转换为字符串,然后一次全部转换为字节?
  • 那你如何在接收端解析它们呢?我的意思是,我怎么知道哪个字节是什么。因为我只会收到一个 byte[] 网格
  • 您可以做几件事。您可以制作一个标准长度的数据包,以便字节数组中的位置范围始终对应于某些变量,或者您可以将字节附加到数组中,告诉您每个变量的开始位置等。
  • 啊好主意! :) 我认为我坚持你的第一个建议。非常感谢,我想我现在可以解决这个问题了:)保重朋友!

标签: java udp


【解决方案1】:

首先,如果您的数据足够小,可以放入单个数据包中,那么 UDP 消息长度不太可能产生太大差异。我建议您不要在这个问题上出汗,除非您有具体证据表明数据包大小是一个关键问题;即硬基准测试结果表明您将无法维持游戏所需的最小传输速率高于特定数据包大小。 (针对实际不存在的问题进行优化是浪费精力。)

如果您关心消息长度,那么您应该使用字符串编码(如上)和二进制编码进行比较;例如就像您使用 DataInputStreamDataOutputStream 一样。

  • byte 将被编码为单个八位字节
  • shortchar 将被编码为两个八位字节

详情请参阅DataOutputStreamjavadocs

不要使用对象流。它们使用与DataOutputStream 相同的二进制编码,但在编码类型信息和对象标识方面存在大量额外开销。

【讨论】:

  • 谢谢! :) 我将从字符串编码转到二进制编码,这应该可以解决我的问题! :)
  • 但首先要检查您的担忧是否有根据。如果不是,那么您的更改将没有什么不同。这将是浪费时间。
【解决方案2】:

我现在已经进行了尝试,它适用于 String,但不是或很长。我自己无法弄清楚错误,也许你们中的一个人能找到错误? 就是这样:

在发送方:

byte[] data = new byte[1024];
        int i = 0;

        String packetNumber = "25";

        ByteBuffer buffer0 = ByteBuffer.allocate(2);
        buffer0.put(packetNumber.getBytes());
        byte[] numberInByte = buffer0.array();

        int x = 0;
        for (int k = i; k < numberInByte.length; k++) {
            data[k] = numberInByte[x];
            x++;
            i++;
        }

        long life = 2000000;

        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(life);
        byte[] lifeInByte = buffer.array();

        x = 0;
        for (int k = i; k < lifeInByte.length; k++) {
            data[k] = lifeInByte[x];
            x++;
            i++;
        }

在接收方:

ByteBuffer byteBuffer = ByteBuffer.wrap(data);

        byte[] packetNumber = new byte[2];
        byteBuffer.get(packetNumber);
        System.out.println(new String(packetNumber));

        long life = byteBuffer.getLong();
        System.out.println(life);

输出是: 25(这是正确的) 1966080(不完全是 2000000,但为什么呢?)

【讨论】:

  • 使用DataOutputStream + ByteArrayOutputStream等,更简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-15
  • 2011-02-07
  • 1970-01-01
  • 2021-04-03
  • 2012-03-30
  • 1970-01-01
相关资源
最近更新 更多