![]() |
|
![]() ![]() ![]() |
|
null56 |
|
||||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Использую методы данного класса, так как он является родственником QSslSocket, поэтому это получается единственный способ чтения и записи от/к сокету...
Как я вижу потоковое взаимодействие с объектом: 1) поступают некоторые данные 2) после поступления конечного сообщения, генериться сигнал readyRead, говоря о том, что доступна новая строка (line) 3) строку можно извлечь методом readLine, указав количество байт для извлечения
или прочитав все накопишиеся данные в устройстве методом
Если я правильно понимаю работу с данным классом, то не понимаю одного - OpenMode
Собственно пример 1) в eventLoop в потоке висит сокет и по таймеру (скажем раз в 5 секунд )проверяет поступившие данные.... то есть он не подключен на реакцию readyRead, что позволит ему накопить некоторый объем данных 2) со стороны клиента я высылаю, за данный промежуток несколько сообщений Вопрос: Как должен вести себя объект QIODevice? Он должен стирать предыдущее сообщение или дописывать в конец предыдущего? Просто, какой бы я режим не пользовал, а имеено
, а так же
разницы не вижу.... в обработчике таймера делаю readLine, мне возвращается конкатенация всех поступивших за данный период сообщений.... какой бы режим я не пользовал, хоть просто запись-чтение, хоть добавляя append Тогда в чем разница? как должно накапливаться сообщение в устройстве? Заранее благодарен за помощь всем откликнувшимся за помощь |
||||||||||
|
|||||||||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Оно накапливается до размера буфера, а потом из буфера стирается столько данных сколько ты прочитал. Если ты буфер не читаешь и он полностью заполнен, то передача данных сервером прекращается пока ты не считаешь данные. Я думаю режимы открытия устройства мало влияют на сокеты. Хотя было бы интересным узнать какие из флагов вообще работают. Например, если поставить QIODevice::ReadOnly будет ли возможным записать что-либо в сокет?
|
|||
|
||||
null56 |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Если на серверной части сделать
то уже на этапе обемена ключами получаем в консоли
Про WriteOnly соответственно
при обмене ключами.... другими словами эти флаги работают Но я просто предполагал, что в случае записи, сохраняется последняя в устройстве строка, а при добавлении (Append) они уже конкатенируются... но видимо ошибся... просто не вижу разницы, что с write, что с append Можно тролям написать узнать... хотя как правильно вопрос сформулировать.. поддержка стабильно отвечает по понедельникам Использование QIODevice::Unbuffered, я так понимаю, тоже не вариант... тогда вообще данных не получу, надо сразу будет их читать по слоту.... |
||||||
|
|||||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
А этот флаг не будет работать для sequential устройств. |
|||
|
||||
kuzulis |
|
||||||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
не, по моему работает даже если у-во 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 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
я думаю, что если бы на каждый доступный байт генерился этот сигнал, то у тогда бы я никогда не вышел из функции обработки этоо сигнала... все таки наверное целиковое сообщение отправленное методом write а точнее конкатенация сообщений, оптравленных методом write до входа обратно в eventloop Это сообщение отредактировал(а) null56 - 3.8.2009, 10:01 |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
null56,
хз.. тут уже нужно смотреть реализацию конкретного класса - наследника от QIODevice ..
ну а попробуйте создать приложение №1 , которое будет , используя QTcpSocket методом write слать приложению №2 пакет с данными размером например 100 Мбайт и посмотрите как часто будет вызываться сигнал readyRead в приложении №2 после того как в приложении №2 мы читаем данные... кстати, интересный вопрос! ![]() Добавлено через 4 минуты и 46 секунд и опять же насчет емита сигнала: если мы цепляемся на этот сигнал readyRead - то он с'эемиттится ОДИН раз при приходе данных (хотя бы 1 байта) ! Но . если мы после этого прочитаем пришедшие в буфер данные - то если придут опять данные - то сигнал с'емиттится еще раз..! Но если мы читать не будем их (данные) -то сигнал только 1 раз с'емиттится.. Я так понимаю это ИМХО т.е все зависит от того, вызывали ли мы ф-ю чтения или нет |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
Просто тогда возникает вопрос... как же тогда определить: когда придет конечное сообщение, а когда только его кусок....
накопить в устройстве сообщение, а потом разделить зная длину сообщения это можно... но я ведь даже длину не знаю как же мне разделять команды, если я даже не знаю, когда закончится соощение7 самому придется какими - то символами отделять сообщение друг от друга? |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Придумывать протокол или взять протокол на основе xml, как Jabber. Ну или использовать http, ftp.
|
|||
|
||||
kuzulis |
|
||||||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
и вот мне интересно насчет принципа выдачи сигнала readyRead() . Я тут просмотрел исходники QAbstractSocket и там есть следующее (QT4.1) :
далее в
и если далее посмотреть реализацию waitForReadOrWrite - то видно , что в итоге используется ф-я select - а она ожидает события прихода хотя-бы одного байта в сокет! Добавлено через 4 минуты и 10 секунд НО мне непонятно, как срабатывает emit readyRead() если мы не вызываем метод waitForReadyRead - а просто коннектимся к сигналу readyRead() ??? ЗЫ: или я где-то "туплю" Добавлено через 6 минут и 45 секунд
Да, SABROG прав! Обычно для этих целей используют механизмы запрос/ответ , запрос/подтверждение и т.п. и тогда никаких коллизий быть не должно! т.е обычно для этих целей используют различные протоколы обмена! |
||||||||
|
|||||||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
SABROG,
kuzulis, отлично, а то что - то я не подумал об этом моменте... для таких целей вполне можно использовать потоковый xml парсер от qt например передавать данные в таком формате
далее в readyReady или по таймеру можно использовать потоковый парсер, например QXmlSteraReader и последовательно добавлять туда данные и сохранять готовые сообщения, а в eventloop проверять этот объект на наличие сообщений Вот так вот, начал тему с непонятки, а пришел к довольно хорошему решению, а то бы дорого мне это обошлось, когда я бы стал сервак тестировать не на локальной машине.... SABROG, kuzulis, огромное спасибо, что помогли разобраться |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
эй! тема не закрыта! теперь давайте мне помогайте!
![]() |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
я не совсем понял, в чем, но если ты про это
то тогда ситуация такая у тебя есть два варианта проверки устройства QIODevice 1) блокирующий режим 2) режим без блокировки в каждом потоке у тебя работает EventLoop, вызываемый функцией exec() он осуществляет всю обработку информации и проверку наличия соединения сиглана readyRead() со слотом... и если на каком - то шаге, когда eventloop проверяет как раз наличие новых данных в буфере, выясняется, что есть функция (slot), которую надо вызвать при появлении новых данных, то в этой функции вызывается, как раз твой слот(ы) про обработке результата waitForReadyRead приостанавливает дальнейший ход работы потока и передает управление eventloop для проверки наличия новых данных и ТОЛЬКО их на определенный промежуток времени, который ты задаешь в параметрах, после чего возвращает управление следующей команде после вызовы waitForReadyRead во... вроде все так, если ничего не напутал... то есть другими словами, эти функции друг другу не нужны, но им обоим нужен запущенный exec Добавлено через 2 минуты и 31 секунду другими словами или ты даешь eventloop возможность тебя оповестить о новых данных или говоришь евентлуп проверять данные прямо сейчас и ни делать более ни фига... |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
а как EventLoop проверит это? откуда он знает что нужно проверять именно наличие новых данных в буфере и емиттить сигнал? ведь для проверки наличия данных в буфере необходимо вызывать метод waitForReadyRead - и ЭТОТ метод уже семиттит сигнал readyRead!!!!! или же цикл EventLoop - ищет во всех методах сигналы , потом проеряет - если сигнал приконнекчен к какому либо слоту - то цикл EventLoop запускает(перебирает) по очереди все методы, в которых есть emit signals (в общем виде)? так чтоли? но если так - то каое время в msecs цикл подставляет в метод для ожидания появления данных ??? |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
30 секунд для waitForReadyRead () и бесконечное, если используется QEventLoop или просто основной цикл событий. Если рассматривать сетевое взаимодействие в Windows, то здесь ОС привязывает свои события (WM_MESSAGES) к окну. Поэтому, когда с сокетом происходит какая-то активность об этом генерится сообщение, которое передается окну. QEventLoop ловит это сообщение и передает объектам, которые могут его обработать. Возможно это QIODevice, возможно какой-то внутренний класс. Но уже этот объект на основе настроек эмитит сигнал readyRead (или любой другой). Поэтому, если цикла событий не существует или он блокирован какой-то долго выполняющейся функцией, то сообщение ставится в очередь и сигнал придет только тогда, когда управление вернется в цикл событий или пока он не будет запущен насильно. Это сообщение отредактировал(а) SABROG - 3.8.2009, 14:35 |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
т.е если я создам свой класс наследник QObject, определю в нем свои сигналы, методы (которые их испускают) и приконнекчу слоты к этим сигналам, то - автоматически цикл событий будет проверять (выполнять) мои методы которые испускают сигналы ? |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Не будет. Нужно вызывать emit, чтобы слоты сработали. |
|||
|
||||
kuzulis |
|
||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
все-равно непонятно... 1. как QEventLoop передает именно пому кому нужно? 2. для отлова события от сокета (рассмотрим виндовс) НЕОБХОДИМО выполнить функцию select! иначе никак не отловим это! неужто QEventLoop - ловит прям каждое событие происходящее в системе? Добавлено через 1 минуту и 1 секунду
а кто тогда вызывает readyRead а ? ![]() |
||||
|
|||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
никто, если он ни с чем не связан Добавлено @ 15:09 суть в том, что связь connect, создает некоторый массив функций, которые нужно будет вызвать, а emit, указывает на небоходимость в данной точке вызова всех функций связанных с ним Это сообщение отредактировал(а) null56 - 3.8.2009, 15:11 |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
так вот на примере с QAbstractSocket - если я делаю connect к readyRead - то тогда какие функции вызовутся для выдачи сигнала readyRead ? ![]() Добавлено через 58 секунд т.е какая ф-я семиттит этот сигнал? |
|||
|
||||
null56 |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 721 Регистрация: 19.3.2008 Репутация: 6 Всего: 12 |
наверное эта
|
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
1. но для этого должна быть вызвана ф-я waitForReadyRead(msecs)!!! 2. кто вызовет ее? 3. какое значение будет у msecs ? |
|||
|
||||
SABROG |
|
|||
![]() Hacker ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2481 Регистрация: 18.9.2006 Репутация: 81 Всего: 91 |
Там не будет никакого значения, зачем оно нужно, если клиент может потенциально держать связь с сервером бесконечное время и не общаться? Например, если подключиться к MySQL серверу, то через часов 8 без активности сервак отключит клиента. Т.е. все это время сигнала readyRead() не будет. Я не думаю, что QAbstractSocket использует waitForReadyRead. |
|||
|
||||
kuzulis |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 154 Регистрация: 5.9.2007 Репутация: нет Всего: 1 |
а каким тогда образом емиттится сигнал readyRead? кто/что его емиттит ? |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets" | |
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |