Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: помогите с QUdpSocket
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
billidean
Приветствую всех.
Накидал приложение на QT 5.1.0, которое общается по Езернету с внешним устройством (плата с ПЛИСкой) с использованием UDP. Код взял с примера.
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    addressClient.setAddress("201.1.1.1");
    udpSocket = new QUdpSocket(this);

    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(read()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initServer()
{
    bool ok = udpSocket->bind(1111);  // Привязка собственного IP-адреса к порту 1111
//    connect(udpSocket, SIGNAL(readyRead()),
//            this, SLOT(read()));
    if( ok )
    {
/*        QMessageBox::information(this, QObject::tr("Server"),
                                       QObject::tr("The server is running on port 1111."));
*/
        ui->label->setText("Init: Ok");
    }
    else
    {
/*        QMessageBox::critical(this, QObject::tr("Server"),
                                       QObject::tr("Error :: %1.\n")
                                       .arg(udpSocket->errorString()));
*/
        ui->label->setText("Init: No");
    }
}

void MainWindow::on_pushButton_clicked()
{
     initServer();
}

void MainWindow::on_pushButton_2_clicked()
{
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);

    out << qint8(16) << qint8(38);

    udpSocket->writeDatagram(data, addressClient, 1111);

//    ui->label_2->setText("Error: " + QString::number(udpSocket->error()));
}

void MainWindow::read()
{
    QByteArray datagram;
    datagram.resize(udpSocket->pendingDatagramSize());
    QHostAddress *address = new QHostAddress();
    quint16 port = 0;
    qDebug() << "read";
//    do
//    {
        udpSocket->readDatagram(datagram.data(), datagram.size(), address, &port);
        qDebug() << "QHostAddress: " << address->toString() << " sourcePort: " << port;
        QDataStream in(&datagram, QIODevice::ReadOnly);
        qDebug() << "size DataGram: " << in.device()->size();

        qint8 a, b;
        in >> a;
        in >> b;
        qDebug() << a << " " << b;
//    }while(udpSocket->hasPendingDatagrams());
}

Данные в сети контролирую WireShark'ом.
Если нажать pushButton_2, то на плату приходит пакет, плата отвечает одной или двумя датаграммами, Qt-приложение принимает эти датаграммы, и все счастливы.
НО!! если плата сама инициирует передачу датаграммы в линию, отмечу САМА, а не в ответ на принятые данные, то Qt-приложение ни.. не реагирует.
Я уже пробовал с платы передавать в разные моменты, после небольшой паузы после двухстороннего обмена, до него, и нифига. Пакеты, отсылаемые с платы в обоих случаях, абсолютно одинаковые (даже идентификаторы пакетов и контр.суммы одинаковые).

Где что попинать, чтобы приложение принимало UDP-пакеты не после отправки своих данных.

З.Ы.: в Qt с сетями почти не работал.
З.З.Ы.: Когда-то делал два приложения клиент-сервер работающие на разных машинах - проблем не было. сервер и клиент принимали/отправляли данные.
gormih
Цитата(billidean @ 9.11.2013, 13:41) *
Данные в сети контролирую WireShark'ом.
Если нажать pushButton_2, то на плату приходит пакет, плата отвечает одной или двумя датаграммами, Qt-приложение принимает эти датаграммы, и все счастливы.
НО!! если плата сама инициирует передачу датаграммы в линию, отмечу САМА, а не в ответ на принятые данные, то Qt-приложение ни.. не реагирует.
Я уже пробовал с платы передавать в разные моменты, после небольшой паузы после двухстороннего обмена, до него, и нифига. Пакеты, отсылаемые с платы в обоих случаях, абсолютно одинаковые (даже идентификаторы пакетов и контр.суммы одинаковые).

Где что попинать, чтобы приложение принимало UDP-пакеты не после отправки своих данных.

З.Ы.: в Qt с сетями почти не работал.
З.З.Ы.: Когда-то делал два приложения клиент-сервер работающие на разных машинах - проблем не было. сервер и клиент принимали/отправляли данные.

А если отладчиком зайти, и посмотреть - возникает ли вообще событие прихода пакета с платы? Проблема скорее всего в этом, и копать туда?
Iron Bug
попробуй так:
udpSocket->bind(QHostAddress::Any, 1111)

и проверь настройки файрволла. что порт 1111 разрешён.
billidean
Цитата(Iron Bug @ 9.11.2013, 15:09) *
и проверь настройки файрволла. что порт 1111 разрешён.

Пока не смотрел, но наверное разрешен, иначе пакеты бы вообще никогда не приходили.

Цитата(gormih @ 9.11.2013, 14:01) *
А если отладчиком зайти, и посмотреть - возникает ли вообще событие прихода пакета с платы? Проблема скорее всего в этом, и копать туда?

у меня в обработчике есть строка
qDebug() << "read";

и если бы было прерывание, то в консоли бы я видел запись. А я ничего не видел.

Цитата(Iron Bug @ 9.11.2013, 15:09) *
udpSocket->bind(QHostAddress::Any, 1111)

Вот это тоже не понятно зачем.
Я понимаю, что обмен по UDP не использует никаких соединений, т.е. посылка вылетела в сеть и всё, забыли про неё, НЕТ никаких запросов и ответов.
НО ПОЧЕМУ тогда при ситуации "сервер отправил - клиент принял + отправил" сервер принимает пакет, а при "просто клиент отправил" сервер не принимает пакет, причем пакеты одинаковые.

Спасибо всем за участие.
Ответ оказался банальным - НЕВНИМАТЕЛЬНОСТЬ. Сто раз все смотрел-пересмотрел, а не увидел разницу в контрольных суммах пакетов, которые передаются из платы в разных ситуациях. В одном случае она равна 0х3c5b, а в другом - 0x3c5d, а я не заметил разницу. Видимо долго сидел и взгляд замылился.
Теперь сделал правильные контрольные суммы в обоих случаях и сервак принимает все пакеты.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2018 IPS, Inc.