【问题标题】:Java/Kotlin UDP datagramJava/Kotlin UDP 数据报
【发布时间】:2019-12-06 17:27:45
【问题描述】:

我有一个非常基本的问题。假设有一个简单的 udp 客户端,它正在侦听传入的数据报。这些数据报只是字节[],但它们可能包含复杂的信息,如字符串、整数等。

是否有任何优雅的方法来解码数据报,例如使用定义数据报内容的结构和 C 中的联合,而不是使用例如逐步处理接收到的 byte[]一个字节缓冲区?

编辑 1

好的,现在试试 FlatBuffers。 我可以建立一个测试项目来玩一点。 我想执行的第一个测试是解析最简单的东西。只有一个短(int16)。我正在使用这个 .fbs 方案

// Example IDL file for our monster's schema.

namespace UDPdatagram;


table DatContent {
    id:short;
}


root_type DatContent;

我尝试运行的最小代码如下:

package controllingFXML

import UDPdatagram.DatContent
import java.nio.ByteBuffer

fun main() {
    // use a short (16 byte int, i.e. 2 byte)
    val byteArray           = ByteArray(2)
    // the test number
    val testShort: Short    = 67
    println("TEST SHORT: $testShort")

    // allocate a byte buffer and add the test short
    val buffer              = ByteBuffer.allocate(byteArray.size)
    buffer.position(0)
    buffer.putShort(testShort)

    // reset the position and verify its content
    buffer.position(0)
    val buffShort           = buffer.short
    println("BUFFER SHORT: $buffShort")

    // reset the position of the buffer again and try to use flatbuffers
    buffer.position(0)
    val content             =  DatContent.getRootAsDatContent(buffer)
    println("PARSED CONTENT: ${content.id()}")
}

不幸的是,在运行代码时,我总是得到以下信息:

Exception in thread "main" java.lang.IndexOutOfBoundsException
    at java.base/java.nio.Buffer.checkIndex(Buffer.java:688)
    at java.base/java.nio.HeapByteBuffer.getInt(HeapByteBuffer.java:392)
    at UDPdatagram.DatContent.getRootAsDatContent(DatContent.java:14)
    at UDPdatagram.DatContent.getRootAsDatContent(DatContent.java:13)
    at controllingFXML.AsdfKt.main(asdf.kt:25)
    at controllingFXML.AsdfKt.main(asdf.kt)

我完全迷路了。我在这里错过了什么?

【问题讨论】:

  • 要么 (i) ByteBuffer 要么 (ii) DataInputStream 环绕 ByteArrayInputStream,在这两种情况下都环绕字节数组。或者直接使用DatagramSocketChannelByteBuffer
  • 您正在尝试自己填充数据,但您也应该使用 FlatBuffers 来完成。您应该在一侧将数据序列化到 FlatBuffers,然后在另一侧从 FlatBuffers 反序列化。
  • 我为什么要这样做?如果我通过数据报通过网络获取数据,它只是一个字节[],不一定是用平面缓冲区构造的。我试图通过直接构造 ByteBuffer 来“模拟”网络数据。这只是一个测试。
  • 这就是平面缓冲区的工作方式。您不能只将 short 推送到缓冲区并使用 flatbuffers 解析它,因为 flatbuffers 使用它自己的数据存储格式。您应该手动解析 byte[](使用 DataInputStream),或者在两侧使用 FlatBuffers 进行数据序列化到/从数据报。
  • 好的,感谢您的澄清。在那种情况下,flatbuffers 对我来说完全没用。我只是在寻找一种更方便的解析字节 [] 的方法。我通过网络从不使用平面缓冲区的来源获取数据。

标签: java kotlin udp decode datagram


【解决方案1】:

Java 中没有像 C 中那样一对一的解决方案。 此外,即使在 C 语言中,它也不是最好的解决方案,因为数据解释取决于系统的字节序。

但 FlatBuffers 库可能有用。

【讨论】:

  • 好的,我看了一下,看起来很不错!但是,本教程在某些时候让我一个人呆着。编译方案后,我究竟应该做什么?没看懂,生成的文件怎么用。
  • 更准确地说:我将生成的文件夹复制到我的项目中。不幸的是,当我构建它时,它指出了几个错误,例如它找不到符号“BaseVector”
  • 我在我的 pom.xml 中包含了 com.google.flatbuffers flatbuffers-java 版本 1.11.1,所以我不明白为什么会出现这些错误...
  • 它根本不会从包中找到 cetrain 东西(如 BaseVector),但会找到其他东西(如 Table)。从 maven 导入的包似乎缺少一些类。怎么可能?
  • 好的,现在我已经克隆了包并手动将其添加到我的项目中。现在它建立了。不知道为什么 Maven 导入不会导入所有内容。
【解决方案2】:

(i) ByteBuffer 或 (ii) DataInputStream 包裹在 ByteArrayInputStream 周围,在这两种情况下都包裹在字节数组中。或者直接使用带有 ByteBuffer 的 DatagramSocketChannel。 – 用户207421

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    • 2011-05-13
    相关资源
    最近更新 更多