Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] QIODevice чтение данных |
Автор: null56 1.8.2009, 13:44 | ||||||||||
Использую методы данного класса, так как он является родственником QSslSocket, поэтому это получается единственный способ чтения и записи от/к сокету... Как я вижу потоковое взаимодействие с объектом: 1) поступают некоторые данные 2) после поступления конечного сообщения, генериться сигнал readyRead, говоря о том, что доступна новая строка (line) 3) строку можно извлечь методом readLine, указав количество байт для извлечения
или прочитав все накопишиеся данные в устройстве методом
Если я правильно понимаю работу с данным классом, то не понимаю одного - OpenMode
Собственно пример 1) в eventLoop в потоке висит сокет и по таймеру (скажем раз в 5 секунд )проверяет поступившие данные.... то есть он не подключен на реакцию readyRead, что позволит ему накопить некоторый объем данных 2) со стороны клиента я высылаю, за данный промежуток несколько сообщений Вопрос: Как должен вести себя объект QIODevice? Он должен стирать предыдущее сообщение или дописывать в конец предыдущего? Просто, какой бы я режим не пользовал, а имеено
, а так же
разницы не вижу.... в обработчике таймера делаю readLine, мне возвращается конкатенация всех поступивших за данный период сообщений.... какой бы режим я не пользовал, хоть просто запись-чтение, хоть добавляя append Тогда в чем разница? как должно накапливаться сообщение в устройстве? Заранее благодарен за помощь всем откликнувшимся за помощь |
Автор: SABROG 1.8.2009, 14:49 |
Оно накапливается до размера буфера, а потом из буфера стирается столько данных сколько ты прочитал. Если ты буфер не читаешь и он полностью заполнен, то передача данных сервером прекращается пока ты не считаешь данные. Я думаю режимы открытия устройства мало влияют на сокеты. Хотя было бы интересным узнать какие из флагов вообще работают. Например, если поставить QIODevice::ReadOnly будет ли возможным записать что-либо в сокет? |
Автор: null56 1.8.2009, 20:04 | ||||||
Если на серверной части сделать
то уже на этапе обемена ключами получаем в консоли
Про WriteOnly соответственно
при обмене ключами.... другими словами эти флаги работают Но я просто предполагал, что в случае записи, сохраняется последняя в устройстве строка, а при добавлении (Append) они уже конкатенируются... но видимо ошибся... просто не вижу разницы, что с write, что с append Можно тролям написать узнать... хотя как правильно вопрос сформулировать.. поддержка стабильно отвечает по понедельникам Использование QIODevice::Unbuffered, я так понимаю, тоже не вариант... тогда вообще данных не получу, надо сразу будет их читать по слоту.... |
Автор: SABROG 1.8.2009, 20:07 |
А этот флаг не будет работать для sequential устройств. |
Автор: kuzulis 3.8.2009, 08:04 | ||||||||
не, по моему работает даже если у-во sequential ! Т.е. буфер отключается ! Я это "заметил" при реализации библиотеки http://www.prog.org.ru/topic_9537_0.html
1. Да 2. Не конечного сообщения - а хотябы одного байта! (вроде) 3. Не факт что извлечете всю строку, т.к. эти методы readLine, raad, readAll читают только то, что уже имеется в буфере! т.е если нам нужно прочитать 100 байт, а пришло 50 - то прочитается 50 .. т.е мы "недочитаем" .. тем более что readAll читает максимум 4096 байт ЗЫ: Если не ошибаюсь Добавлено через 3 минуты и 47 секунд
эмм.. в методах read и write перед чтением идет проверка на корректность флагов вот:
|
Автор: null56 3.8.2009, 09:58 | ||
я думаю, что если бы на каждый доступный байт генерился этот сигнал, то у тогда бы я никогда не вышел из функции обработки этоо сигнала... все таки наверное целиковое сообщение отправленное методом write а точнее конкатенация сообщений, оптравленных методом write до входа обратно в eventloop |
Автор: kuzulis 3.8.2009, 10:50 | ||
null56, хз.. тут уже нужно смотреть реализацию конкретного класса - наследника от QIODevice ..
ну а попробуйте создать приложение №1 , которое будет , используя QTcpSocket методом write слать приложению №2 пакет с данными размером например 100 Мбайт и посмотрите как часто будет вызываться сигнал readyRead в приложении №2 после того как в приложении №2 мы читаем данные... кстати, интересный вопрос! ![]() Добавлено через 4 минуты и 46 секунд и опять же насчет емита сигнала: если мы цепляемся на этот сигнал readyRead - то он с'эемиттится ОДИН раз при приходе данных (хотя бы 1 байта) ! Но . если мы после этого прочитаем пришедшие в буфер данные - то если придут опять данные - то сигнал с'емиттится еще раз..! Но если мы читать не будем их (данные) -то сигнал только 1 раз с'емиттится.. Я так понимаю это ИМХО т.е все зависит от того, вызывали ли мы ф-ю чтения или нет |
Автор: null56 3.8.2009, 11:07 |
Просто тогда возникает вопрос... как же тогда определить: когда придет конечное сообщение, а когда только его кусок.... накопить в устройстве сообщение, а потом разделить зная длину сообщения это можно... но я ведь даже длину не знаю как же мне разделять команды, если я даже не знаю, когда закончится соощение7 самому придется какими - то символами отделять сообщение друг от друга? |
Автор: SABROG 3.8.2009, 11:10 |
Придумывать протокол или взять протокол на основе xml, как Jabber. Ну или использовать http, ftp. |
Автор: kuzulis 3.8.2009, 11:27 | ||||||||
и вот мне интересно насчет принципа выдачи сигнала readyRead() . Я тут просмотрел исходники QAbstractSocket и там есть следующее (QT4.1) :
далее в
и если далее посмотреть реализацию waitForReadOrWrite - то видно , что в итоге используется ф-я select - а она ожидает события прихода хотя-бы одного байта в сокет! Добавлено через 4 минуты и 10 секунд НО мне непонятно, как срабатывает emit readyRead() если мы не вызываем метод waitForReadyRead - а просто коннектимся к сигналу readyRead() ??? ЗЫ: или я где-то "туплю" Добавлено через 6 минут и 45 секунд
Да, SABROG прав! Обычно для этих целей используют механизмы запрос/ответ , запрос/подтверждение и т.п. и тогда никаких коллизий быть не должно! т.е обычно для этих целей используют различные протоколы обмена! |
Автор: null56 3.8.2009, 11:57 | ||
SABROG, kuzulis, отлично, а то что - то я не подумал об этом моменте... для таких целей вполне можно использовать потоковый xml парсер от qt например передавать данные в таком формате
далее в readyReady или по таймеру можно использовать потоковый парсер, например QXmlSteraReader и последовательно добавлять туда данные и сохранять готовые сообщения, а в eventloop проверять этот объект на наличие сообщений Вот так вот, начал тему с непонятки, а пришел к довольно хорошему решению, а то бы дорого мне это обошлось, когда я бы стал сервак тестировать не на локальной машине.... SABROG, kuzulis, огромное спасибо, что помогли разобраться |
Автор: kuzulis 3.8.2009, 12:07 |
эй! тема не закрыта! теперь давайте мне помогайте! ![]() |
Автор: null56 3.8.2009, 12:28 | ||
я не совсем понял, в чем, но если ты про это
то тогда ситуация такая у тебя есть два варианта проверки устройства QIODevice 1) блокирующий режим 2) режим без блокировки в каждом потоке у тебя работает EventLoop, вызываемый функцией exec() он осуществляет всю обработку информации и проверку наличия соединения сиглана readyRead() со слотом... и если на каком - то шаге, когда eventloop проверяет как раз наличие новых данных в буфере, выясняется, что есть функция (slot), которую надо вызвать при появлении новых данных, то в этой функции вызывается, как раз твой слот(ы) про обработке результата waitForReadyRead приостанавливает дальнейший ход работы потока и передает управление eventloop для проверки наличия новых данных и ТОЛЬКО их на определенный промежуток времени, который ты задаешь в параметрах, после чего возвращает управление следующей команде после вызовы waitForReadyRead во... вроде все так, если ничего не напутал... то есть другими словами, эти функции друг другу не нужны, но им обоим нужен запущенный exec Добавлено через 2 минуты и 31 секунду другими словами или ты даешь eventloop возможность тебя оповестить о новых данных или говоришь евентлуп проверять данные прямо сейчас и ни делать более ни фига... |
Автор: kuzulis 3.8.2009, 13:26 | ||
а как EventLoop проверит это? откуда он знает что нужно проверять именно наличие новых данных в буфере и емиттить сигнал? ведь для проверки наличия данных в буфере необходимо вызывать метод waitForReadyRead - и ЭТОТ метод уже семиттит сигнал readyRead!!!!! или же цикл EventLoop - ищет во всех методах сигналы , потом проеряет - если сигнал приконнекчен к какому либо слоту - то цикл EventLoop запускает(перебирает) по очереди все методы, в которых есть emit signals (в общем виде)? так чтоли? но если так - то каое время в msecs цикл подставляет в метод для ожидания появления данных ??? |
Автор: kuzulis 3.8.2009, 14:36 | ||
т.е если я создам свой класс наследник QObject, определю в нем свои сигналы, методы (которые их испускают) и приконнекчу слоты к этим сигналам, то - автоматически цикл событий будет проверять (выполнять) мои методы которые испускают сигналы ? |
Автор: SABROG 3.8.2009, 14:41 | ||
Не будет. Нужно вызывать emit, чтобы слоты сработали. |
Автор: kuzulis 3.8.2009, 14:42 | ||||
все-равно непонятно... 1. как QEventLoop передает именно пому кому нужно? 2. для отлова события от сокета (рассмотрим виндовс) НЕОБХОДИМО выполнить функцию select! иначе никак не отловим это! неужто QEventLoop - ловит прям каждое событие происходящее в системе? Добавлено через 1 минуту и 1 секунду
а кто тогда вызывает readyRead а ? ![]() |
Автор: null56 3.8.2009, 15:07 | ||
никто, если он ни с чем не связан Добавлено @ 15:09 суть в том, что связь connect, создает некоторый массив функций, которые нужно будет вызвать, а emit, указывает на небоходимость в данной точке вызова всех функций связанных с ним |
Автор: kuzulis 3.8.2009, 15:15 | ||
так вот на примере с QAbstractSocket - если я делаю connect к readyRead - то тогда какие функции вызовутся для выдачи сигнала readyRead ? ![]() Добавлено через 58 секунд т.е какая ф-я семиттит этот сигнал? |
Автор: null56 3.8.2009, 15:21 | ||
наверное эта
|
Автор: kuzulis 3.8.2009, 15:38 | ||
1. но для этого должна быть вызвана ф-я waitForReadyRead(msecs)!!! 2. кто вызовет ее? 3. какое значение будет у msecs ? |
Автор: SABROG 3.8.2009, 16:38 |
Там не будет никакого значения, зачем оно нужно, если клиент может потенциально держать связь с сервером бесконечное время и не общаться? Например, если подключиться к MySQL серверу, то через часов 8 без активности сервак отключит клиента. Т.е. все это время сигнала readyRead() не будет. Я не думаю, что QAbstractSocket использует waitForReadyRead. |
Автор: kuzulis 4.8.2009, 07:36 | ||
а каким тогда образом емиттится сигнал readyRead? кто/что его емиттит ? |