Russian Qt Forum

Qt => Вопросы новичков => Тема начата: ___Cepera___ от Март 10, 2016, 14:54



Название: Не срабатывает слот при получении сигналk
Отправлено: ___Cepera___ от Март 10, 2016, 14:54
Qt4.8.7. Такая ситуация, есть серверный udpsocket, клиент шлет сообщение, сервер прочитал пришедшее сообщение от клиента, отправил его на обработку в другой поток, и при определенных перешедших данных, начинаем бесконечно слать обратно клиенту ответные сообщения. Остановка отправки сообщений осуществляется специальным сообщением от клиента, так вот когда клиент отправляет сообщение на остановку непрерывной передачи, серверный udpsocket не переходит в слот обработки. Как можно поставить приоретет на выполнения слота по пришедшему сигналу? ну или вообще может какие то предположения будут.
Все сообщения от сервера клиенту доходят. С 1 сообщением тоже все работает хорошо. Поток по сути ни как не влияет. Отправка ответного сообщения идет не из потока. В потоке только обработка. Единственный вариант, который мне пришел в голову, в ручную проверять udpsocket на наличее данных при бесконечной отправки сообщений.


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: Bepec от Март 10, 2016, 15:10
"бесконечно отправляет" - а время для обработки приходящего сообщения есть, или же у вас там for стоит голый?


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: ___Cepera___ от Март 10, 2016, 15:20
Бесконечная отправка работает так. При получении сообщения на бесконечнную отправку, в потоке ставится флаг. Потом формируется сообщение и шлется сигнал на отправку сформированного сообщения. После отправки сообщения клиенту, в поток шлется сигнал, поток смотрит, если стоит флаг на отправку сообщения, формирует его и опять шлет сигнал на отправку сформированного сообщения и так пока не придет сообщение от клиента на остановку.


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: gil9red от Март 10, 2016, 16:00
добавьте какую-нибудь задержку, хоть в 1 миллисекунду


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: ___Cepera___ от Март 10, 2016, 16:27
Самое смешное ставил задержку в 1 и более секунду через sleep в потоке, не помогало, ответные сообщения приходили дольше, но сообщения клиента так же не приходили, но поставил в 1 секунду таймер в основном потоке программы перед отправкой сообщения, заработало отлично)
Странно, но получается наверное сокет не успевает освободиться Потому что делал, чтобы сервер отправлял 200 сообщений, сообщение серверу на остановку приходило после отправки этих 200 сообщений. Программа сервер еще пока идет отправка без таймера зависает,  хотя не должна. Можно как то решить еще эту проблему без таймера?


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: Bepec от Март 10, 2016, 19:58
Поправив ваш код, можно совершить всё что угодно, "даже в космос полететь". Но без предмета разговора делать нечего :D


Название: Re: Не срабатывает слот при получении сигналk
Отправлено: ___Cepera___ от Март 13, 2016, 20:27
Код выложить не могу, поэтому накидал простенькое приложение для тестирования на сколько возможно максимум в windows в секунду отправлять udp сообщений получилось около 15000.
Такая проблема, перенес отправку сообщений в отдельный поток, ставил там задержку, поставил потоку низкий приоритет, он все равно не дает работать основному потоку. В основном потоке запускается таймер на 1 секунду, но поток для отправки не дает сработать таймауту. Ниже прилагаю код. Делал отправку по таймауту таймера в 1 милисекунду работает хорошо, но странно,что когда делал через сон потока в 1 секунду, поток опять блокирует основной поток программы. Посоветуйте как правильно реализовать отправку udp сообщений, чтобы выжимать максимум в windows и чтобы можно было останавливать отправку.
Код:
#include "server.h"

Server::Server() :
    QObject()
{
    udpSock = new QUdpSocket();
    connect(udpSock, SIGNAL(readyRead()), this, SLOT(readUDP()));
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
    stopSend = new QTimer(this);
    connect(stopSend, SIGNAL(timeout()), this, SLOT(stopSendMess()));
    stop = true;
}
Server :: ~Server()
{
    udpSock->close();
}
bool Server :: bind_port(quint16 port, quint16 _serverPort, QHostAddress _serverAddress)
{

    if(udpSock->bind(port))
    {
        serverPort = _serverPort;
        serverAddress = _serverAddress;
        emit message("Подключение выполнено");
        udpsend = new UdpSend(serverAddress, serverPort);\
        connect(udpsend, SIGNAL(finished()), udpsend, SLOT(deleteLater()));
        connect(this, SIGNAL(start(QUdpSocket*,bool*)), udpsend, SLOT(send(QUdpSocket*,bool*)));
        return true;
    }
    else
        emit message("Подключение не выполнено");
    return false;
}

void Server::close_port()
{
    udpSock->close();
    udpsend->quit();
    emit message("Отключение выполнено");
}

void Server :: send_data_UDP(QString text)
{
    QByteArray _message = text.toLocal8Bit();
    QDataStream out(&_message, QIODevice::WriteOnly);
    out.setVersion(QDataStream :: Qt_4_8);
    udpSock->writeDatagram(_message, serverAddress, serverPort);
}
void Server :: readUDP()
{
    QByteArray receiveData;
    int nbytes = udpSock->pendingDatagramSize();
    receiveData.resize(nbytes);
    udpSock->readDatagram (receiveData.data(), nbytes);
    emit append_message(receiveData);
    if(receiveData == "stop")
        stop = true;
    else if(stop)
    {
        stop = false;
        stopSend->start(1000);
        emit start(udpSock, &stop);

    }

}
void Server :: endless_send() //Через таймер работает хорошо, интерфейс не блокируется
{
    if(!stop)
        timer->start(1);
}
void Server :: timeout()
{
    timer->stop();
    send_data_UDP("hello");
    endless_send();

}
void Server :: stopSendMess()
{
    udpSock->close();
    stop = true;
    stopSend->stop();
}


Поток для отправки
Код:
#include "udpsend.h"

UdpSend::UdpSend(QHostAddress _address, quint16 _port) :
    QThread()
{
    address = _address;
    port = _port;
    start(QThread :: LowestPriority);
}
void UdpSend :: run()
{
    exec();
}
void UdpSend :: send(QUdpSocket * udpSocket, bool * send)
{
    QString text = "hello";
    while(*send == false)
    {
        msleep(1);
        QByteArray _message = text.toLocal8Bit();
        QDataStream out(&_message, QIODevice::WriteOnly);
        out.setVersion(QDataStream :: Qt_4_8);
        udpSocket->writeDatagram(_message, address, port);
    }
}