【问题标题】:How to read a QTcpSocket from R如何从 R 中读取 QTcpSocket
【发布时间】:2017-11-20 20:25:37
【问题描述】:

我正在尝试将数据从 Qt 发送到 R。我是 QtNetwork 模块的新手,对 Qt 整体而言相对较新。因此,我也试图弄清楚 QIODevice 如何为读取和写入目的对数据进行编码。

如果我运行 Fortune Server Example 并使用 R 中的以下代码连接到它:

connection <- socketConnection(host="localhost", port=50743, open="rb", timeout=10)
readBin(connection, what="raw", n = 1000)

返回以下原始十六进制向量

00 00 00 56 00 59 00 6f 00 75 00 20 00 77 00 69 00 6c 00 6c 00 20 00 66 00 65 00 65 00 6c 00 20 00 68 00 75 00 6e 00 67 00 72 00 79 00 20 00 61 00 67 00 61 00 69 00 6e 00 20 00 69 00 6e 00 20 00 61 00 6e 00 6f 00 74 00 68 00 65 00 72 00 20 00 68 00 6f 00 75 00 72 00 2e

删除前五个字节和所有剩余的空字符并转换为我得到的字符:

"You will feel hungry again in another hour."

所以我想知道的是,所有不属于财富的角色是从哪里来的?第四个字节似乎是消息从第六个字节到结尾的字节长度,其余的“非幸运”字符全部为空。

我读到 QByteArray 以空字符终止每个字节,并且 QByteArray 在被 QTcpSocket 写入之前被转换为 QBuffer,这是这里发生的事情吗? QBuffer 增加了消息的长度(但其他四个字节的长度)并且 QByteArray 的每个第二个字节都是空字符?另外,最后一个字节不为空(readBin 操作是否消耗了它/readBin 是如何知道消息在哪里结束的)?

这是向套接字写入数据的唯一方法吗?如果我想传输 double 类型的值,我是否必须将它们转换为 QByteArray 才能以这种方式传输它们?是不是有一些非文本的方式通过套接字传输数据?

任何启示将不胜感激!

编辑:

感谢您的回答!为了完整起见,这里是您如何解码 R

中的字符串
connection <- socketConnection(host="localhost", port=50743, open="rb", timeout=10)

# Read first 32 bits, which contains the size of the string in bytes
len.raw <- readBin(connection, what="raw", n = 4)

# convert to integer
len <- strtoi(paste(c("0x",len.raw),collapse=""))

# Read raw message
msg.raw <- readBin(connection, what="raw", n = len)

# convert to char using UTF-16BE
msg <- iconv(list(msg.raw),from="UTF-16BE")

close(connection)

cat(msg)

【问题讨论】:

    标签: c++ r qt sockets


    【解决方案1】:

    如果你看一下 Fortune Server Example 是如何实现的,你会发现它使用QDataStream 在套接字上序列化财富(QStrings):

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    
    out << fortunes.at(qrand() % fortunes.size());
    

    因此,问题被简化为“QDataStream 如何序列化QStrings?”,这在有关serializing Qt data types 的文档页面中得到了广泛的回答。可以看到QString的序列化是这样的:

    • 如果字符串为空:0xFFFFFFFF (quint32)
    • 否则:以字节为单位的字符串长度 (quint32),后跟 UTF-16 格式的数据

    这正是您在问题中看到的。前四个字节是以字节为单位的字符串长度,您稍后看到的“空值”由于使用了UTF-16 编码而出现。


    这是向套接字写入数据的唯一方法吗?如果我想传输 double 类型的值,我是否必须将它们转换为 QByteArray 才能以这种方式传输它们?是不是有一些非文本的方式通过套接字传输数据?

    你可以使用任何你喜欢的serialization formatQDataStream 在 Qt 中被广泛使用,因为它支持大多数开箱即用的 Qt 数据类型。这与使用QByteArray无关,可以让QDataStream直接写入socket。如您所见,QDataStream 实际上是一种二进制格式(非文本)。如果想要人类可读的文本格式,可以使用JSON

    但是,如果您打算使用 QDataStream 将数据从 Qt 发送到 R,则必须为 R 编写您的 QDataStream 反序列化器。我建议使用一些在 C++ 和 R 中实现的常见数据序列化(代替重新发明轮子)。我相信 JSON 符合这个标准,如果你想使用二进制格式,msgpack 可能对你很感兴趣,因为它支持很多编程语言(包括 R 和 C++)。

    【讨论】:

    • 感谢您,这是一个巨大的帮助。特别是在我的情况下,您不知道自己在寻找什么。
    猜你喜欢
    • 1970-01-01
    • 2013-11-09
    • 2017-07-18
    • 1970-01-01
    • 2018-01-09
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多