C++ 从QTcpSocket读取(多个)值(快速)

C++ 从QTcpSocket读取(多个)值(快速),c++,qt,qtcpsocket,qdatastream,C++,Qt,Qtcpsocket,Qdatastream,我正在使用一个测量设备,它使用tcp套接字发送(二进制)浮点值,最高可达70 kHz 我的目标是尽快读取这些值,并在程序的其他部分使用它们 到目前为止,我能够使用QTcpSocket和QDataStream逐值提取值: 首先,我创建套接字并将流连接到它 mysock = new QTcpSocket(this); mysock->connectToHost(ip, port); QDataStream stream(mysock); stream.setByteOrder(QDataStr

我正在使用一个测量设备,它使用tcp套接字发送(二进制)浮点值,最高可达70 kHz

我的目标是尽快读取这些值,并在程序的其他部分使用它们

到目前为止,我能够使用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;
    }
}
  • 扩展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;
}
if(mysock->waitForReadyRead())
{
stream.startTransaction();
char*c=新字符[40];
stream.readRawData(c,40);//我想知道里面到底是什么
QByteArray a(c);

qDebug()您的代码有几个错误

在使用
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);
    } 
}

编辑:

评论如下:

如果我错了,请纠正我,但如果我想丢弃2个字节,我需要执行“stream>>someint(2字节)>>somefloat(4字节)”?我如何处理流中的许多值


你的代码有几个错误

在使用
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);
    } 
}

编辑:

评论如下:

如果我错了,请纠正我,但如果我想丢弃2个字节,我需要执行“stream>>someint(2字节)>>somefloat(4字节)”?我如何处理流中的许多值



你能告诉我马克斯速率是多少字节吗?读一大块字节并计算它,以确保所有字节都在你的套接字缓冲器中接收。然后在循环之前删除<代码> QByTurReX <代码>。不要在一个循环中定义一个新的内存部分,定义一个缓冲器,然后附加到它。首先考虑QT是一个事件驱动的框架。这不是最好的方法。应该会有帮助。我同意@TheDarkKnight。可能你看到了性能问题,你想:“让我们使用线程来提高性能”,而不是理解这个问题。多线程是很难的。它的bug非常难找到,因此,既然你是新手,在获得一些经验之前,不要使用它们。这将为你节省大量的时间和痛苦。你能告诉我最大速率是多少字节吗?读取更大的字节并计数,以确保你的袜子中接收到所有字节在循环之前删除<代码> qBytErra<代码>。不要在循环中定义一个新的内存部分,定义一个缓冲区,然后附加到它。首先考虑QT是一个事件驱动的框架。这不是最好的方法。应该会有帮助。我同意@TheDarkKnight。可能你看到了性能问题,你想:“让我们使用线程来提高性能”,而不是理解这个问题。多线程是很难的。因为它的bug非常难找到,所以既然你是新手,在获得一些经验之前不要使用它们。这将为你节省大量时间和痛苦。似乎我把QTcpSocket与QDataStream结合的概念弄错了。如果你能解释一下你的第一个错误,那就太好了更详细一点。您关于二进制格式的问题:6字节,0xff 0xff表示前2个字节,然后4个字节包含浮点值(单精度)。要使用startTransaction(),我需要升级QT(我使用的是5.6)当你写到旧的qt时,它没有缓存。至少我检查了Qt4.8的源代码,它直接从套接字读取数据,以防执行事务时它有缓存。我检查了qt源代码,我错了:(.
QDataStream
没有任何类型的缓冲区,这是由IODevice(套接字)处理的。我能够更新到QT5.8(msvc2013 32位没有预编译的QT5.9)。调整了您的代码并使其运行。似乎我从未理解>>运算符。如果我错了,请更正我,但如果我希望丢弃2个字节,我需要执行“stream>>someint(2字节)>>somefloat(4字节)”?我如何处理流中的许多值?我是否需要在流上循环>>然后?
QStream
数据以定义的endian处理的二进制方式读取数据,无论您运行的是什么平台。Qt也处理具有big endian的平台。它还有助于维护具有耦合标准和不同平台上的浮点数他可以有多种格式。大多数网络标准是
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);