Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QUdpSocket在高频环境中的极限_C++_Qt_Event Handling_Udp_Qudpsocket - Fatal编程技术网

C++ QUdpSocket在高频环境中的极限

C++ QUdpSocket在高频环境中的极限,c++,qt,event-handling,udp,qudpsocket,C++,Qt,Event Handling,Udp,Qudpsocket,我的任务是以~10kHz的读取速率处理UDP数据。我正在使用Qt5.13.1(MinGW32),所以我尝试使用QUdpSocket 我做了一个简单的测试程序,但结果有点令人沮丧。readyRead()信号太慢了。由于某些原因,每2-4个信号就会有超过1或2毫秒的延迟。 我制作了一个简单的包计数器,并将其与wireshark中的内容进行比较。果然有数据包丢失 我可以做些什么来提高绩效?或者这只是Qt事件循环的极限 我用QtCreator4.10.0运行它。在Windows7上 更新:根据您的建议:

我的任务是以~10kHz的读取速率处理UDP数据。我正在使用Qt5.13.1(MinGW32),所以我尝试使用
QUdpSocket

我做了一个简单的测试程序,但结果有点令人沮丧。
readyRead()
信号太慢了。由于某些原因,每2-4个信号就会有超过1或2毫秒的延迟。
我制作了一个简单的包计数器,并将其与wireshark中的内容进行比较。果然有数据包丢失

我可以做些什么来提高绩效?或者这只是Qt事件循环的极限

我用QtCreator4.10.0运行它。在Windows7上

更新:根据您的建议:我尝试了:

  • 在不同的线程中移动套接字。这会使性能更好一些 .. 一点点

  • LowDelayOption=1-我没有注意到任何更改

  • ReceiveBufferSizeCheckTopion-我没有注意到任何更改

  • 阅读时不使用QDebug-我没有检查它,只是用于 收集统计数据
  • udpproc.h

    #ifndef UDPPROC_H
    #define UDPPROC_H
    
    #include "QObject"
    #include "QUdpSocket"
    #include "QHostAddress"
    #include "QThread"
    
    #include "QDebug"
    #include "networker.h"
    
    class UDPProc : public QObject
    {
        Q_OBJECT
    public:
        UDPProc();
        ~UDPProc();
    private:
        QUdpSocket dataServerSocket;
        NetWorker* netWorker;
        QThread netThread;
    
    
    };
    
    #endif // UDPPROC_H
    
    udpproc.cpp

    UDPProc::UDPProc() {

    netWorker=新的netWorker(&dataServerSocket);
    netWorker->moveToThread(&netThread);
    netWorker->getInnerLoop()->moveToThread(&netThread);
    连接(&netThread,SIGNAL(started()),netWorker,插槽(serversocketprocessing());
    连接(&this->dataServerSocket,SIGNAL(readyRead()),netWorker->getInnerLoop(),SLOT(quit());
    QString address=“127.0.0.3:16402”;
    QHostAddress ip(地址拆分(“:”)位于(0));
    quint16端口=地址.split(“:”).at(1).toUShort();
    绑定(ip,端口);
    //setSocketOption(QAbstractSocket::LowDelayOption,1);
    dataServerSocket.moveToThread(&netThread);
    netThread.start();
    //dataServerSocket.setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption,128000);
    //qDebug()pendingDatagramSize());
    }
    如果(乘以.size()>=10000){
    长和=0;
    用于(整数x:次){
    
    //qDebug()在测量代码的时间关键部分时,我建议避免使用qDebug(或任何其他慢速打印/调试功能)。它可能会对实际测量产生太大的影响

    我的建议是,将从QElapsedTimer接收到的计时值存储到单独的容器(例如QVector,或者仅存储一个随时间平均的qint64),并且每隔一段时间只显示一次调试消息(每秒或仅在最后显示一次)。这样,测量造成的开销影响较小。较长时间内的平均值也将有助于测量结果的差异

    我还建议您使用QeReleasedTimer::nsecsAppeased,以避免在高频情况下出现舍入问题,因为QeReleasedTimer::Appeased将始终舍入到最接近的毫秒(并且您已经在1ms区域内测量)

    在实际显示结果时,始终可以将纳秒转换为毫秒


    以10kHz频率接收的数据大小是多少?

    在测量代码的时间关键部分时,我建议避免使用qDebug(或任何其他慢速打印/调试功能)。它可能会对实际测量产生太大的影响

    我的建议是,将从QElapsedTimer接收到的计时值存储到单独的容器(例如QVector,或者仅存储一个随时间平均的qint64),并且每隔一段时间只显示一次调试消息(每秒或仅在最后显示一次)。这样,测量造成的开销影响较小。较长时间内的平均值也将有助于测量结果的差异

    我还建议您使用QeReleasedTimer::nsecsAppeased,以避免在高频情况下出现舍入问题,因为QeReleasedTimer::Appeased将始终舍入到最接近的毫秒(并且您已经在1ms区域内测量)

    在实际显示结果时,始终可以将纳秒转换为毫秒


    您以10kHz的速率接收的数据大小是多少?

    您无法在Windows上以如此高的速率接收套接字数据包。这是操作系统的限制。即使使用并将接收代码移动到无限循环中,如下所示:

    socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
    ...
    
    for (;;)
    {
        if(socket->waitForReadyRead(1)) // waits for some events anyway
        {
            // read here
        }
    }
    
    或者,您可以在数据包结构中嵌入一些时间代码字段,并将几个数据包一起发送,或者使用一些不会丢失数据包的连接。例如,使用,因为套接字的下一种情况是可能的:

    • 收到完整数据包
    • 只收到了数据包的一部分
    • 一起收到了几个包
    另外,不要尝试

    如果缓冲区大小被限制为某个大小,QAbstractSocket将不会 缓冲区大于此数据大小。例外情况下,缓冲区大小为 0表示读取缓冲区不受限制,并且所有传入数据都不受限制 缓冲。这是默认值

    如果您仅在中的某些点读取数据,则此选项非常有用 时间(例如,在实时流媒体应用程序中)或 保护您的套接字,防止接收太多数据,这可能会 最终导致应用程序内存不足

    只有QTcpSocket使用QAbstractSocket的内部缓冲区;QUdpSocket 根本不使用任何缓冲,而是依赖于隐式 操作系统提供的缓冲。因此,调用 QUdpSocket上的此函数无效


    您无法在Windows上以如此高的速率接收套接字数据包。这是操作系统的限制。即使使用并且如果将您的接收代码移动到无限循环中,如下所示:

    socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
    ...
    
    for (;;)
    {
        if(socket->waitForReadyRead(1)) // waits for some events anyway
        {
            // read here
        }
    }
    
    或者,您可以在数据包结构中嵌入一些时间代码字段,并将几个数据包一起发送,或者使用一些不会丢失数据包的连接。例如,使用,因为套接字的下一种情况是可能的:

    • #include "networker.h" NetWorker::NetWorker(QUdpSocket *dataServerSocket) { this->dataServerSocket = dataServerSocket; } NetWorker::~NetWorker() { delete dataServerSocket; } QEventLoop *NetWorker::getInnerLoop() { return &loop; } void NetWorker::serverSocketProccessing() { while(true){ timer.start(); loop.exec(); times<<timer.nsecsElapsed(); while(dataServerSocket->hasPendingDatagrams()){ dataServerSocket->readDatagram(buffer, dataServerSocket->pendingDatagramSize()); } if (times.size() >= 10000){ long long sum = 0; for (int x : times){ //qDebug()<<x; sum += x; } qDebug() << "mean: "<<sum/times.size(); break; } } }
    socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
    ...
    
    for (;;)
    {
        if(socket->waitForReadyRead(1)) // waits for some events anyway
        {
            // read here
        }
    }