从 QTcpSocket 读取(许多)值(快速)
Read (many) values from QTcpSocket (fast)
我正在使用一种测量设备,该设备使用高达 70 kHz 的 TCP 套接字发送(二进制)浮点值。
我的目标是尽快读取这些值并将它们用于我程序的其他部分。
到目前为止,我可以使用 QTcpSocket 和 QDataStream 按值提取值:
首先我创建套接字并将流连接到它
mysock = new QTcpSocket(this);
mysock->connectToHost(ip, port);
QDataStream stream(mysock);
stream.setByteOrder(QDataStream::LittleEndian);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
然后我从套接字中读取并将流数据写入我的浮点值
while(true) //only for test purpose (dont stop reading)
if (mysock->waitForReadyRead())
{
while (mysock->bytesAvailable() >= 6)
{
QByteArray a = mysock->read(6); //each value sent is 6 bytes long
stream.skipRawData(2); //first 2 bytes don't belong to the number
float result;
stream >> result;
//qDebug()<<result;
}
}
当我测量 while(true) 循环的迭代频率时,我能够达到大约 30 kHz。
每次读取多个值我可以达到 70 Khz。 (不考虑其他计算可能会减慢我的速度)
我的问题是:
- 如果我一次读取多个值,如何从 QDataStream 中提取这些值?我需要 6 个字节的间距,其中只有 4 个字节包含值。
答案: 在我的例子中有 2 个字节(垃圾)后跟已知数量的值,例如 4 个字节用于浮点数,4 个字节用于另一个浮点数,2 uint16 的字节。
stream >> trashuint16 >> resultfloat1 >> resultfloat2 >> resultuint16
- 扩展 1:我可以将我的设备配置为发送不同类型(int、float)的不同值,这些值需要写入不同的变量。
答案:同理。
- 是否有更有效的方法从 QTcpSocket 读取多个值?
回答:在评论中回答
更新(回答一些问题):
- 以字节为单位的最大速率:70 kHz x 6 字节(对于一个值)= 420 kB/s(似乎没有那么多:))
更新 2
- 新问题:当我开始交易时(使用
stream.startTransaction
),我想知道二进制代码中的流中有什么。
- 我不明白
QDataStream::startTransaction
是如何工作的。将读取多少字节?我不使用 >>
提取的数据会怎样?
我试过以下方法:
if (mysock->waitForReadyRead())
{
stream.startTransaction();
char *c = new char[40];
stream.readRawData(c, 40); //I want to know whats really inside
QByteArray a(c);
qDebug() << a <<stream.status();
if (!stream.commitTransaction())
break;
}
一次又一次地这样做,我有时会得到 status = -1(读得太多)有时不会。如何获取流的"size"?
您的代码有几个错误。
您在使用 QDataStream
的同时正在从套接字直接读取。这会破坏东西。
此外,您的代码假设您的应用程序将接收与另一端发送的数据块相同的数据块。你没有这样的保证!您可能会收到在帧中间结束的块数据。它的工作完全靠运气,或者您忽略了应用程序的一些错误。
这应该是这样的:
while(true)
if (mysock->waitForReadyRead()) // IMO doing such loop is terrible approach
// but this is Out of the scope of question, so ignoring that
{
while (true)
{
stream.startTransaction();
float result;
qint32 somedata
stream >> somedata >> result; // I do not know binary format your application is using
if (!in.commitTransaction())
break;
AddDataToModel(result, somedata);
}
}
编辑:
来自评论:
Please correct me if I'm wrong, but if I want 2 bytes to be discarded I need to do "stream >> someint(2 byte) >> somefloat(4 byte)"? How can I handle many values in stream?
qint16 toBeDiscarded;
float value;
// note stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
// is needed to read float as 32 bit floating point number
stream >> toBeDiscarded >> value;
ProcessValue(value);
我正在使用一种测量设备,该设备使用高达 70 kHz 的 TCP 套接字发送(二进制)浮点值。
我的目标是尽快读取这些值并将它们用于我程序的其他部分。
到目前为止,我可以使用 QTcpSocket 和 QDataStream 按值提取值:
首先我创建套接字并将流连接到它
mysock = new QTcpSocket(this);
mysock->connectToHost(ip, port);
QDataStream stream(mysock);
stream.setByteOrder(QDataStream::LittleEndian);
stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
然后我从套接字中读取并将流数据写入我的浮点值
while(true) //only for test purpose (dont stop reading)
if (mysock->waitForReadyRead())
{
while (mysock->bytesAvailable() >= 6)
{
QByteArray a = mysock->read(6); //each value sent is 6 bytes long
stream.skipRawData(2); //first 2 bytes don't belong to the number
float result;
stream >> result;
//qDebug()<<result;
}
}
当我测量 while(true) 循环的迭代频率时,我能够达到大约 30 kHz。 每次读取多个值我可以达到 70 Khz。 (不考虑其他计算可能会减慢我的速度)
我的问题是:
- 如果我一次读取多个值,如何从 QDataStream 中提取这些值?我需要 6 个字节的间距,其中只有 4 个字节包含值。
答案: 在我的例子中有 2 个字节(垃圾)后跟已知数量的值,例如 4 个字节用于浮点数,4 个字节用于另一个浮点数,2 uint16 的字节。
stream >> trashuint16 >> resultfloat1 >> resultfloat2 >> resultuint16
- 扩展 1:我可以将我的设备配置为发送不同类型(int、float)的不同值,这些值需要写入不同的变量。
答案:同理。
- 是否有更有效的方法从 QTcpSocket 读取多个值?
回答:在评论中回答
更新(回答一些问题):
- 以字节为单位的最大速率:70 kHz x 6 字节(对于一个值)= 420 kB/s(似乎没有那么多:))
更新 2
- 新问题:当我开始交易时(使用
stream.startTransaction
),我想知道二进制代码中的流中有什么。 - 我不明白
QDataStream::startTransaction
是如何工作的。将读取多少字节?我不使用>>
提取的数据会怎样?
我试过以下方法:
if (mysock->waitForReadyRead())
{
stream.startTransaction();
char *c = new char[40];
stream.readRawData(c, 40); //I want to know whats really inside
QByteArray a(c);
qDebug() << a <<stream.status();
if (!stream.commitTransaction())
break;
}
一次又一次地这样做,我有时会得到 status = -1(读得太多)有时不会。如何获取流的"size"?
您的代码有几个错误。
您在使用 QDataStream
的同时正在从套接字直接读取。这会破坏东西。
此外,您的代码假设您的应用程序将接收与另一端发送的数据块相同的数据块。你没有这样的保证!您可能会收到在帧中间结束的块数据。它的工作完全靠运气,或者您忽略了应用程序的一些错误。
这应该是这样的:
while(true)
if (mysock->waitForReadyRead()) // IMO doing such loop is terrible approach
// but this is Out of the scope of question, so ignoring that
{
while (true)
{
stream.startTransaction();
float result;
qint32 somedata
stream >> somedata >> result; // I do not know binary format your application is using
if (!in.commitTransaction())
break;
AddDataToModel(result, somedata);
}
}
编辑:
来自评论:
Please correct me if I'm wrong, but if I want 2 bytes to be discarded I need to do "stream >> someint(2 byte) >> somefloat(4 byte)"? How can I handle many values in stream?
qint16 toBeDiscarded;
float value;
// note stream.setFloatingPointPrecision(QDataStream::SinglePrecision);
// is needed to read float as 32 bit floating point number
stream >> toBeDiscarded >> value;
ProcessValue(value);