Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UdpSocket
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
leonneon_89
Добрый день! Столкнулся с такой проблемой. Есть устройство которое посылает сообщения раз в 1 миллисекунду, в своей программе я получаю эти сообщения, с разной периодичностью по времени, от 3-4 миллисекунд до 100 микросекунд, измеряю время получения сообщений по средством функций QueryPerformanceCounter и QueryPerformanceFrequency, мне нужно получать сообщения с равной периодичностью по времени равной 1 мс в своей программе. Как этого добиться, есть какие нибудь варианты?
В своей программе использую QUdpSocket. Размер сообщения 13 байт.
Пример приема сообщения.
    QByteArray datagram;

    while (udpSocket_->hasPendingDatagrams())
    {
        datagram.resize(udpSocket_->pendingDatagramSize());
        udpSocket_->readDatagram(datagram.data(), datagram.size());
        QDataStream in(&datagram, QIODevice::ReadOnly);
        in.setVersion(QDataStream::Qt_4_7);

        quint8 firstCommand = 0;
        in >> firstCommand;

        if(firstCommand == 8)
        {
            quint8 secondCommand = 0;
            in >> secondCommand;

            if(secondCommand == responseOperationController_)
            {
                in >> message_.unitShifterFirst >> message_.unitShifterSecond;
                in >> message_.attenuatorValueD1 >> message_.attenuatorValueD2 >> message_.attenuatorValueD4;
                in >> message_.voltageValueD1 >> message_.amperageValueD1 >> message_.voltageValueD2 >> message_.amperageValueD2;
                in >> message_.voltageValueD4 >> message_.amperageValueD4;

                //Здесь мы получаем значение необходимых нам битов
                clearWasteBits(3, message_.attenuatorValueD1);
                clearWasteBits(3, message_.attenuatorValueD2);
                clearWasteBits(3, message_.attenuatorValueD4);

                emit sendMessageKu(message_);
            }
        }
    }

Слот в котором принимаю сообщение вызывается при испускании объекта udpSocket сигнала readyRead().
Буду очень рад, если вы выскажите ваши мысли или возможные пути решения по этому вопросу.
Iron Bug
во-первых, UDP не гарантирует доставки сообщения.
во-вторых, при 1 сообщении в миллисекунду получится 1000 сообщений в секунду. каков размер сообщения? посчитай, хватит ли скорости твоей сети для прокачки такого траффика?
ну и любые операции ввода-вывода с потоками очень тормозные и нельзя их запихивать в обработку сообщений. можно буферизовать сообщения, а в отдельном потоке их разбирать.

ну и ещё: и генератор, и приёмник должны запускаться с очень высоким приоритетом.
leonneon_89
Цитата(Iron Bug @ 1.10.2013, 18:06) *
во-первых, UDP не гарантирует доставки сообщения.
во-вторых, при 1 сообщении в миллисекунду получится 1000 сообщений в секунду. каков размер сообщения? посчитай, хватит ли скорости твоей сети для прокачки такого траффика?
ну и любые операции ввода-вывода с потоками очень тормозные и нельзя их запихивать в обработку сообщений. можно буферизовать сообщения, а в отдельном потоке их разбирать.

ну и ещё: и генератор, и приёмник должны запускаться с очень высоким приоритетом.

Спасибо задачу решил, размер тела сообщения 13 байт, скорость передачи сети Ethernet 10 Mбит/c, так что этого хватает для перекачки трафика. На счет буферизации, для этой задачи она не приемлема, т.к. нужно каждый раз актуальные данные. Задачу решил путем создания класса QThread, в котором создал слот для приема дейтаграммы и считывал приходящие в него сообщения.
Если кому нибудь интересно выкладываю пример решения заголовочный файл класса треда:
#include <QThread>
#include <QUdpSocket>

class ControllerThread : public QThread
{
    Q_OBJECT

public:
    explicit ControllerThread(QObject *parent = 0);
    void run();

public slots:
    void processPendingDatagrams();
    void getSocketDescriptor(QUdpSocket*);

private:
    QUdpSocket *udpSocket_;
};


Исходный файл класса:
#include "operateController_thread.h"

ControllerThread::ControllerThread(QObject *parent) :
    QThread(parent)
{
    udpSocket_ = new QUdpSocket;
}

void ControllerThread::processPendingDatagrams()
{
    QByteArray datagram;
    while (udpSocket_->hasPendingDatagrams())
    {
        datagram.resize(udpSocket_->pendingDatagramSize());
        udpSocket_->readDatagram(datagram.data(), datagram.size());
        QDataStream in(&datagram, QIODevice::ReadOnly);
        in.setVersion(QDataStream::Qt_4_7);

        quint8 firstCommand = 0;
        in >> firstCommand;

        if(firstCommand == 8)
        {
            quint8 secondCommand = 0;
            in >> secondCommand;

            if(secondCommand == 3)
            {
                 //Здесь я вытаскиваю оставшуюся часть сообщения.
            }
        }
    }
}

void ControllerThread::getSocketDescriptor(QUdpSocket *socket)
{
    if(socket != NULL)
        udpSocket_ = socket;
}

void ControllerThread::run()
{
    qDebug() << "Get KU states thread.";
    exec();
}


Далее в конструкторе родителя создаю объекты:
udpSocket_ = new QUdpSocket;
thread_ = new ControllerThread;

После бинда сокета, связываю объекты:
connect(udpSocket_,SIGNAL(readyRead()),thread_,SLOT(processPendingDatagrams()), Qt::DirectConnection);
connect(this,SIGNAL(sendSocketDescriptor(QUdpSocket*)),thread_, SLOT(getSocketDescriptor(QUdpSocket*)));
emit sendSocketDescriptor(udpSocket_); //Посылаю указатель сокета треду.
udpSocket_->moveToThread(thread_); //Помещаю сокет в созданный тред.
thread_->start(QThread::TimeCriticalPriority); //Стартую тред с высоким приоритетом.

В общем почти, но остается создать еще некоторые коннекты для завершения потока.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.