Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Http и потоки
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
bo0blik
Буду рад если кто-то поделится исходниками на эту тему, очень интересно посмотреть.
ViGOur
А что именно интересует?
В том, чтобы самому писать, ничего сложного нет! :)
bo0blik
Я просто из тех людей которые пока не увидят код, ничего не поймут.

Просто интересует распределенная много-поточная отправка http запросов.
Elfinit
Вот примерчик. Набор классов для выполнения разных типов запросов с разными параметрами. Примеры использования:
GET:
WebGetRequest *g = new WebGetRequest(QUrl("http://www.google.ru"),"./check_internet.xml");
connect(g,SIGNAL(done(WebReply)),this,SLOT(check_internet_done(WebReply)));
connect(g,SIGNAL(offline()),this,SLOT(internet_offline()));
g->run();

POST:
QFile file("C:/image.jpeg");
file.open(QIODevice::ReadOnly);
QByteArray data = file.readAll();
file.close();
WebPostRequest *p = new WebPostRequest(QUrl("http://send.photo.here.com"),"image/jpeg",data,data.size(),"answer.xml");
connect(p,SIGNAL(done(WebReply)),this,SLOT(send_image_done(WebReply)));
connect(p,SIGNAL(offline()),this,SIGNAL(not_connected()));
p->run();


Заботиться больше ни о чём (в т.ч. об удалении экзепляров) не нужно, в принципе, даже ответ обрабатывать необязательно, т.е. можно сразу после создания объекта вызывать run. Естественно, обработка любого числа запросов будет происходить параллельно. Плюс имеются сигналы разные (download/upload progress, errors, etc.). И пустые слоты, которые можно заполнить на свой вкус)

И ещё - НЕ используй QHttp. Мои классы написаны на основе QNetworkAccessManager
bo0blik
Elfinit, спасибо большое, про http я уже досконально изучил, просто интересно как это правильней всего с потоками выглядит.

Я посмотрел класс, очень интересный пример.

Если у кого еще есть что-нибудь буду очень благодарен.
Elfinit
Цитата(bo0blik @ 2.10.2009, 5:43) *
Elfinit, спасибо большое, про http я уже досконально изучил, просто интересно как это правильней всего с потоками выглядит.

Я посмотрел класс, очень интересный пример.

Если у кого еще есть что-нибудь буду очень благодарен.

Ммм...А зачем вообще париться с потоками в данном случае, за тебя всё библиотека сделает..Главное-инициировать запрос и в нужное время отреагировать на ответ..
rnd
сегодня тоже провозился пол-дня. Пытался сделать из асинхронного режима запросов синхронный, для чего пускал qttp в отдельном потоке - так и не удалось победить - вешается зараза в WaitForMultipleObjects
BRE
Цитата(rnd @ 6.10.2009, 21:36) *
сегодня тоже провозился пол-дня. Пытался сделать из асинхронного режима запросов синхронный, для чего пускал qttp в отдельном потоке - так и не удалось победить - вешается зараза в WaitForMultipleObjects

Как-то связи синхронного режима с отдельным потоком не понял?

Вот набросок кода, думаю идея должна быть понятна:
QByteArray loader()
{
        QHttp http;
        http.setHost( ... );
        http.get( ... );

        while( http.state() != QHttp::Closing )
                QApplication::processEvents();

        return http.readAll();
}

BRE
Для того, что бы сделать работу QHttp синхронной, нужно что бы отрабатывали QSocketNotifier. Для этого нужно крутить eventloop (именно там происходят необходимые действия). Предыдущий пример показывал саму идею, "боевой" код я бы сделал примерно таким:
QByteArray loader()
{
        QHttp http;
        QEventLoop loop;
        QObject::connect( &http, SIGNAL( done( bool ) ), &loop, SLOT( quit() ) );

        http.setHost( ... );
        http.get( ... );
        loop.exec();
    // выходим из цикла при получении сигнала QHttp::done

    // Проверили ошибки....
        qDebug() << http.state() << http.error() << http.bytesAvailable();
        return http.readAll();
}


Если необходимо сделать отдельный поток, который делает запрос и получает/обрабатывает ответ, то такой код можно использовать и в методе run потока.
rnd
BRE, то, что вы предлагаете - очень опасная практика. Начнут прокачиваться сообщения, т.е. вызываться слоты\обработчики, которые в данный момент времени (посреди работы функции) вызываться совершенно не должны.

Именно поэтому и создается отдельный поток, в который засовывается(moveToThread) объект QNetworkAccessManager там для него и идет прокачка сообщений, а вызывающий поток ждет.

Вчерашняя проблема решилась заменой QHttp на QNetworkAccessManager:)
BRE
Цитата(rnd @ 7.10.2009, 13:57) *
BRE, то, что вы предлагаете - очень опасная практика. Начнут прокачиваться сообщения, т.е. вызываться слоты\обработчики, которые в данный момент времени (посреди работы функции) вызываться совершенно не должны.

Как ты себе это представляешь? Какие не нужные слоты начнут отрабатывать посреди работы этой функции. Можно по-подробней. Желательно с примерами.
Если этот код будет выполняться в отдельном потоке, то и очередь сообщений будет использоваться этого потока.
Кстати, не имеет значения что использовать QHttp или QNetworkAccessManager.
rnd
Цитата(BRE @ 7.10.2009, 14:03) *
Как ты себе это представляешь? Какие не нужные слоты начнут отрабатывать посреди работы этой функции. Можно по-подробней. Желательно с примерами.


В смысле какие слоты? Обычные слоты, естественно emit которым был сделан из другого потока. Да и вообще, начнут вызываться все обработки - неважно слот, метаколл или эвент. Если пример еще нужен - могу привести.

Цитата(BRE @ 7.10.2009, 14:03) *
Кстати, не имеет значения что использовать QHttp или QNetworkAccessManager.


Как оказалось - имеет, QNetworkAccessManager не виснет в WaitForMultipleObject, почему различия - выяснять не стал
BRE
Цитата(rnd @ 7.10.2009, 14:18) *
В смысле какие слоты? Обычные слоты, естественно emit которым был сделан из другого потока. Да и вообще, начнут вызываться все обработки - неважно слот, метаколл или эвент. Если пример еще нужен - могу привести.

Конечно нужны примеры.
Какие ненужные слоты начнут выполняться? По-подробней.

Цитата(rnd @ 7.10.2009, 14:18) *
выяснять не стал

Зря, что не стал.

Ты считаешь, что при таком коде ненужные слоты вызываться не будут:
void Thread::run()
{
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), SLOT( replyFinished(QNetworkReply*) ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );

    exec();
}


а при таком будут?
void Thread::run()
{
    QEventLoop loop;
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), &loop, SLOT( quit() ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );
    loop.exec();
}

rnd
Ну смотри, допустим в очереди лежит два сообщения - на вызов Class1::slot1 и Class1::slot2. Вызывается slot1() - объект переходит в несогласованное состояние. Начинаем прокачку сообщений - сразу вызыватеся slot2, т.е. колл-стек такой:

----------------
slot2()
...
slot1()
...
-----------------

Поскольку объект в несогласованном состоянии (выполнение slot1 еще не закончилось) - ахтунг!

Цитата(BRE @ 7.10.2009, 14:22) *
Зря, что не стал.

За это не платят:)
BRE
Цитата(rnd @ 7.10.2009, 14:30) *
Ну смотри, допустим в очереди лежит два сообщения - на вызов Class1::slot1 и Class1::slot2. Вызывается slot1() - объект переходит в несогласованное состояние. Начинаем прокачку сообщений - сразу вызыватеся slot2, т.е. колл-стек такой:

Мне лучше на примере кода показать.
Откуда взялись сообщения, кто их туда положил? Вообще, как ты себе все это представляешь.

Продублирую сообщение. Вот примерный код двух разных потоков. Что бы разговор был более предметным.

Ты считаешь, что при таком коде ненужные слоты вызываться не будут:
void Thread::run()
{
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), SLOT( replyFinished(QNetworkReply*) ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );

    exec();
}


а при таком будут?
void Thread::run()
{
    QEventLoop loop;
    QNetworkAccessManager manager;
    connect( &manager, SIGNAL( finished(QNetworkReply*) ), &loop, SLOT( quit() ) );
    manager.get( QNetworkRequest( QUrl("http://qtsoftware.com") ) );
    loop.exec();
    // обработка ответа...
}


Где и какие ненужные сообщения/сигналы/слоты будут вызываться?
rnd
Давай отвлечемся от QNetworkAccessNanager - он тут совершенно не при чем сейчас

Смотри, есть два потока, в первом крутится obj1, во втором obj2:

Thr1 | Thr2
------ ------
Obj1 | Obj2


Первый поток эмитит два сигнала sig1, sig2 объекту, который находится во втором потоке.
Obj1 ->sig1->Obj2
Obj1 ->sig2->Obj2

Соответствующие слоты(slot1, slot2) не вызываются напрямую, а в очередь Thr2 кладутся сообщения для вызова этих слотов.


Дальше, Thr2 извлекает очередное сообщение, видит что это вызов слота slot1 - и вызывает его. Объект Obj2 переходит в несогласованное состояние. Внутри слота slot1 мы начинаем прокачивать сообщения (loop.exec()), Thr2 извлекает следующие сообщение из очереди - видит что это вызов слота slot2 и дергает его - опа приехали, еще не выйдя из slot1 уже запустили slot2!
Callstack:
----------
slot2()
.....
slot1()
....
------------

Естественно, вместо вызова слотов могут быть любые обработчики.

Для того чтобы решить эту проблему - и создается дополнительный поток - Thr3. В него помещается объект и сообщения этот объект получает в нем. А вызывающие поток ждет окончания Thr3 НЕ прокачивая при этом свои сообщения.
BRE
Тебе не кажется, что это немного надуманный пример.
Я привел тебе код, который будет работать в потоке синхронно.
Если существует возможность такой ситуации, о которой пишешь ты, то такие случаи нужно учитывать отдельно (например использовать Qt::BlockingQueuedConnection), а лучше так никогда не делать.
А прокрутка очереди сообщений, это вовсе не опасная практика. Она повсеместно используется в Qt: от оживления длительных операций и до модальных диалогов. Главное думать, что делаешь.
rnd
Надуманный?:)
Это крайне упрощенный пример.

Мне сложно представить многопоточное приложение, использующие очереди, в котором несанкционированная прокачка сообщений не будет проблемой. На эти грабли наступали уже не раз.
Приложение, над которым сейчас работаем активно использует пул потоков, пересылку сообщений между ними и минимум синхронизаций. Использование прокачки сообщений в коде - запрещено.
Кстати модальные диалоги - тоже не айс, именно по этой причине.

Я не говорю, что это должна быть запрещенная практика, просто многие люди не задумываются, что реально происходит при таком подходе. И каждое использование прокачки сообщений должно быть обдумано несколько раз, со всеми возможными последствиями.
BRE
Цитата(rnd @ 8.10.2009, 9:54) *
Мне сложно представить многопоточное приложение, использующие очереди, в котором несанкционированная прокачка сообщений не будет проблемой. На эти грабли наступали уже не раз.
Приложение, над которым сейчас работаем активно использует пул потоков, пересылку сообщений между ними и минимум синхронизаций. Использование прокачки сообщений в коде - запрещено.

Такие ситуации возникают тогда, когда нитка запущена и в пустую крутит цикл обработки сообщений, ожидая прихода внешнего события. После чего в своем контексте выполняет необходимый код. К тому же у вас в контексте этой нити можно выполнять разный код (в зависимости от слота).
Вопрос: для чего эта нить висит и ждет этого события? Наверное лучше в нужный момент запустить нить, которая выполнит необходимое действие и завершиться.
А если нужны сложности, конечно можно ограничивать себя по "самые помидоры" и держать активную нить, которая будут пытаться в своем контексте выполнять множество разных действия. ;) :)

Цитата(rnd @ 8.10.2009, 9:54) *
Я не говорю, что это должна быть запрещенная практика, просто многие люди не задумываются, что реально происходит при таком подходе. И каждое использование прокачки сообщений должно быть обдумано несколько раз, со всеми возможными последствиями.

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