LINUX.ORG.RU

Клиент на QTcpSocket (чтение и запись на диск)

 ,


0

1

Подскажите пожалуйста в какую сторону копать. Я хочу сделать клиент на QTcpSocket, который должен получать данные, обрабатывать и записывать их на диск. Так как обработка и запись новых данных занимает какое-то время, то как лучше это сделать в рамках Qt? Не делать же все в слоте подключенному к сигналу readyRead QTcpSocket'а.

Сомневаюсь, что обработка и запись занимает так много времени, чтобы обычное подключение сигнала к слоту приводило к проблемам. Но если по каким-то причинам это не так, вынеси обработку в отдельный поток (потоки, если её можно распараллелить)

XMs ★★★★★
()

У TCP ведь есть буфер на уровне ОС? Ничего страшного, отпустит диск - будешь жевать следующий пакет, не беда, не пропадут данные? Или я не прав?

I-Love-Microsoft ★★★★★
()

На выбор: QThread если хочешь больше контроля над тредом, QRunnable если хочешь просто запустить таску и тебе не нужно возвращаемое значение, QtConcurrent и QFuture если нужно.

fluorite ★★★★★
()
Ответ на: комментарий от fluorite

Скорее всего у меня не возникнет ситуации, что системный буфер будет перезаписываться и можно обрабатывать и записывать данные прямо в слоте, подключенному к readyRead. С другой стороны средняя скорость записи на HDD ~150 Мб/с.

До этого я извользовал системные библиотеки сокетов и мьютексов. Но как лучше решить эту же задачу в Qt?

GrandmaSquid3
() автор топика
Ответ на: комментарий от GrandmaSquid3

Так проще всего будет. Вообще запись на диск как правило быстрей сети.

Ну или в слоте забрасывать данные в thread-safe очередь и в другом потоке из нее уже и писать на диск. При этом не забывая, что эта очередь потенциально в бесконечность может вырасти (т.е. предусматривая механизм приостановки чтения из сокета если диск тормозит).

dvetutnev
()
Ответ на: комментарий от GrandmaSquid3

Системный буфер перезаписываться не будет вообще.

dvetutnev
()

Не делать же все в слоте подключенному к сигналу readyRead QTcpSocket'а.

Можно подумать, что есть какой-то другой способ.

annulen ★★★★★
()

Ну разве что отказаться от QTcpSocket и сделать на простом сокете, тогда есть вариант с zero-copy, но в постановке задачи есть слово «обрабатывать» - значит не подойдет

annulen ★★★★★
()
Ответ на: комментарий от fluorite

Может уткнуться в C10k_problem

как её можно решать в рамках qt - увеличить буфера приема и максимальное количества открытых файлов ?

x905 ★★★★★
()
Ответ на: комментарий от x905

Сделать воркер-тредов и ставить таски в очередь. Не писать high-load сервер на фреймворке для прикладных приложений, а переписать на boost::asio или libuv там. От задачи зависит.

fluorite ★★★★★
()
Ответ на: комментарий от annulen

Например, куда-то копировать считанные данные из сокета, а обрабатывать и записывать на диск в другом потоке. Тогда системный буфер не успеет начать перезаписываться. Я так и делал, когда не использовал Qt, но сейчас нужно реализовать все на Qt. Как грамотнее сделать это на Qt?

С одной стороны с Qt проще, особенно GUI, а с другой стороны вносится неопределенность.

GrandmaSquid3
() автор топика
Ответ на: комментарий от annulen

А если убрать слово «обрабатывать», то запись данных в файл непосредственно в слоте, подключенному к сигналу readyRead, это нормально? Без какого-либо дополнительного потока или фичи Qt?

GrandmaSquid3
() автор топика
Ответ на: комментарий от GrandmaSquid3

Нормально вполне. Если бы данные приходили быстрее, чем ты их обрабатываешь и пишешь на диск, рано или поздно тебе в любом случае никаких буферов не хватит.

unC0Rr ★★★★★
()
Ответ на: комментарий от fluorite

Не писать high-load сервер на фреймворке для прикладных приложений

qtcore не подходит для high-load по какой причине, из-за сигналов-слотов ?

x905 ★★★★★
()
Ответ на: комментарий от x905

Я про qtcore ничего не говорил, я имел ввиду, что qnetwork сделан для удобной кросс-платформенной разработки. Соответственно, задачи выжать максимум из конкретного железа под конкретной ОС не ставилось. А сигнал-слоты раскрываются в обычные вызовы функций, с чего бы им быть лимитирующим фактором?

fluorite ★★★★★
()
Ответ на: комментарий от GrandmaSquid3

Еще раз: с TCP системный буфер не будет перезаписываться, у него есть flow control.

При заполнении буфера в QTcpSocket, его реализация перестает забирать из буфера ядра ОС данные. Пока данные из ядра не забраны в прикладное приложение, ядро не пошлет серверу (другой стороне) подтверждение, что данные приняты. Сервер будет дальше с периодически с увеличивающейся задержкой повторно отправлять кусок данных, который не подтвержден (и если твой клиент уж очень тормозной, то когда-нибудь просто закроет соединение).

Это все касается TCP. С UDP, при заполнении буферов вновь поступающие данные отбрасываются.

dvetutnev
()
Ответ на: комментарий от fluorite

в чем тогда отличие qnetwork и boost::asio или libuv при обработке сетевого обмена, что его лучше не применять при больших сетевых нагрузках ?

x905 ★★★★★
()
Ответ на: комментарий от fluorite

Реализация на линуксе использует системный вызов poll.

в качестве ликбеза - чтоже тогда следует использовать вместо poll при highload ?

x905 ★★★★★
()
Ответ на: комментарий от GrandmaSquid3

Например, куда-то копировать считанные данные из сокета, а обрабатывать и записывать на диск в другом потоке.

Этого можно добиться, если QTcpSocket будет принадлежать одному потоку, а объект со слотом-обработчиком - другому, например с помощью moveToThread. Тогда вызов слота будет перебрасывать данные из одного потока в другой

А если убрать слово «обрабатывать», то запись данных в файл непосредственно в слоте, подключенному к сигналу readyRead, это нормально? Без какого-либо дополнительного потока или фичи Qt?

Зависит от условий. Если интерфейс не подлагивает, то особого смысла в лишнем потоке нет.

Другое дело, что если нет «обрабатывать», то можно взять splice() и гнать данные из сокета в файл без их копирования в юзерспейс. Но это уже без QTcpSocket

annulen ★★★★★
()
Ответ на: комментарий от fluorite

Реализация на линуксе использует системный вызов poll

Раньше вообще был select :)

Т.е. highload из коробки не получится, надо пердолиться с QAbstractEventDispatcher, и решение это будет платформозависимое.

QEventLoop вообще не очень эффективная штука, и QIODevice тоже. Так что просто вкрутить готовый QAbstractEventDispatcher на epoll с жилхаба - это не панацея

annulen ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.