【问题标题】:Deserialize QByteArray to Java data types将 QByteArray 反序列化为 Java 数据类型
【发布时间】:2013-11-26 19:26:21
【问题描述】:

我目前正在处理客户端-服务器连接。

客户端是用 Java 编写的,不使用在 Android 手机上运行的 QT,服务器是使用 Qt 框架 用 C++ 编写的。

客户端收到 QByteArraysQStringsQLists,但我不知道如何反序列化和解释传入的数据。

创建我必须在 java 客户端读取的数据包的 C++ 源代码如下所示:

QByteArray body;
QString string1, string2, string3;
QList<float> list;
qint8 recognitionCount;

QDataStream bodyStream(&body, QIODevice::WriteOnly);

bodyStream << recognitionCount;

bodyStream << string1.toUtf8()
<< string2.toUtf8()
<< string3.toUtf8()
<< list;

客户端和服务器之间的连接已启动并运行良好。例如,我了解如何读取服务器发送给我的整数。我也知道如何读取字节,但我应该如何处理这些字节?例如,如何将它们格式化为字符串?

谁能帮帮我?

非常感谢任何帮助!

【问题讨论】:

  • 如何通过网络发送数据?
  • TCP 套接字和 DataInputStream
  • 问题是你是如何序列化数据的。 QList 和 QByteArray 是类型,而不是协议/格式(我会考虑使用 XML 或 Json 之类的东西,除非你真的需要二进制格式)
  • 所以如果你使用 QTcpSocket 和 DataInputStream 你已经知道客户端会收到什么,它不是 QByteArray 也不是 Qlist!你必须做逆运算来构建你的数据
  • 我编辑了我的问题并添加了格式化数据包的 c++ 代码。我希望它现在更清楚。不幸的是,我必须使用这种二进制格式并且不能使用 XML 或 JSON。

标签: java c++ qt deserialization qbytearray


【解决方案1】:

您可以像这样将 Qt 字符串转换为 Java(根据 this definition):

final static int MAX_STRING_LENGTH = 10240; // arbitrary number
private final static ByteBuffer stringBytes = ByteBuffer.allocate(MAX_STRING_LENGTH);

static String readStringFromQTStream(final ObjectInputStream in) throws IOException {
  if (in.available() < (Integer.SIZE / 8)) { // check that there are at least 4 bytes for the length
    throw new IOException("Illegal data received: expected integer but only got " + in.available() + " bytes");
  }
  final int stringLength = in.readInt();
  if (stringLength == 0xFFFFFFFF) { // Qt for null string
    return null;
  }
  if ((stringLength < 0) || (stringLength > stringBytes.capacity())) { // check for malformed data
    throw new IOException("Illegal data received: string with supposed length of " + stringLength + " bytes");
  }

  stringBytes.clear(); // global var, not thread-safe!
  in.readFully(stringBytes.array(), 0, stringLength);
  stringBytes.flip();
  return StandardCharsets.UTF_8.decode(stringBytes).toString();
}

请注意,ByteBuffer 是复用的,如果你经常读取数据,这是一个很好的性能提升,但是如果没有进一步的代码,这当然不是线程安全的。

【讨论】:

  • 确实;为了规避线程安全问题,您可以在本地声明stringBytes。我不明白您为什么要从安全的解决方案开始。过早的优化?
  • 自从 ThreadLocal 发明以来,可能没有理由不这样做(除了代码演示的简单性)。但是在函数内部声明它会导致大量的创建开销,因为生成一个 ByteBuffer 比一个简单的数组要昂贵得多。
【解决方案2】:

QDataStream 的格式记录在例如http://qt-project.org/doc/qt-4.8/datastreamformat.html。这应该告诉您将其反序列化为 Java 类型需要了解的内容。

【讨论】:

    【解决方案3】:

    在您的服务器上,您必须知道客户端“询问”什么并正确回答。 在客户端同样,您必须了解服务器的“答案”。 因此,您必须在服务器和客户端之间创建自己的通信“协议”。

    通过线路交换的只是一个字节序列,而不是 QByteArray 也不是 QList

    QTcpSocket 的 API 为您提供了您需要了解的客户端连接的一切(如果应用程序应该支持多个客户端,那么您的业务就是使其成为可能)以及如何写入插座。

    在客户端几乎相同,但我从未在 Android 上开发过,所以无法提出任何建议。

    我的answer 非常简要地解释了如何在 Qt 中构建应用程序客户端-服务器。也许会有用。

    【讨论】:

    • 您好,感谢您的回答。实际上,我确实有一个协议,并且我知道这些网络概念。客户端和服务器之间的连接运行良好,例如,当服务器向我发送 Integer 时我没有任何问题,因为我知道它的大小并且只需要从流中读取下一个 Integer。但是,当服务器向我发送 QByteArrays 之类的对象时,我不知道我应该阅读什么。我现在没有使用QTcpSocket(我没有在服务器端工作,我只知道协议)。在客户端,我使用的是用于套接字的 Java 标准库。
    【解决方案4】:

    如果有人遇到这个帖子:

    我建议改用Protocol Buffers 进行在线数据传输。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-14
      • 2013-11-20
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多