Здравствуйте!
В Ubuntu в программе на Qt-4.7.2 обнаружилось, что метод QTcpSocket readAll(),
наследуемый от QIODevice, ведёт себя по-разному в зависимости от того, откуда
читаются данные. Если им читаются данные от web-камеры по сигналу readyRead(),
то он работает, как и ожидается - возвращает сразу все переданные данные.
От камеры идёт поток кадров в jpg, 12 раз в секунду, можно и чаще. В камере
запущен TCP-сервер, с которым TcpSocket в программе соединяется через порт 80.
Если же я в этой же программе создаю свой QTcpServer, чтобы другая программа
могла с ним соединяться и получать от него данные, то передающая сторона
постоянно, тоже 12 раз в секунду, посылает подсоединившемуся клиенту данные,
там может быть более 400 000 байтов, то в программе-клиенте QTcpSocket несколько
раз вырабатывает сигнал readyRead(), при этом может быть так, что по первым пяти-семи
сигналам читается 0, а по последнему считывается весь посланный массив, либо он может
считываться двумя или тремя порциями на эти 8 сигналов, а по остальным читается 0 байтов,
при этом обе программы запущены на одном компьютере, порт назначен 6000.
CPU Intel Core 2 Quad 2400MHz.
Чем это объясняется и как побороть? М.б., данные передаются слишком медленно?
Если массив передавать порциями по 16384 байта и остаток, а читать тоже по 16384
и в последний раз остаток, то эти порции читаются сразу. Разумеется, перед этим надо
послать клиенту, например, в восьми байтах, число посылок и размер остатка, но я заметил,
что при таком способе клиент не успевает принимать массивы с той же частотой, с которой
их посылает сервер. Отладочная печать сообщает, что послано столько-то, а принято меньше.
Другой вариант - всё же посылать весь массив и в клиенте накапливать ненулевые
результаты чтения, перед этим опять же надо будет послать размер массива, но этого
я ещё не пробовал.
Т.е. почему такая разница в чтении от камеры и от программы? Действительно из-за
задержек или почему? Если передавать порциями по 32768 или 64000 байтов, тоже иногда
по сигналу reradyRead() читается 0 байтов. Есть какие-нибудь рекомендации на это случай?
Пётр.
readAll() from TcpServer
Пока выяснилось следующее - когда клиент соединяется с сервером, то по readAll()
к нему сначал приходят три непонятных посылки, разделённые нулевыми результатами
вызовов readAll(). Сначала приходит 65536 байтов, потом два раза 0, потом 147456, потом
ещё раза два 0, потом 212992 байта, что является суммой двух первых, а потом начинают
идти ожидаемые пакеты, также разделённые тремя или четырьмя нулевыми.
Оказалось, что и от камеры что-то похожее. Ту программу писал не я и выяснилось,
что, хотя камера посылает 12 кадров в секунду, подпрограмма, работающая с ней,
принимает около трети приходящих кадров, т.е. за минуту к ней должно придти 720,
а дальше она пересылает, например, 225.
Пётр.
вы сигнал finished() обрабатываете или только readyRead()?
Только readyRead(), как в оставшейся программе.
Пётр.
Попробуйте обработать и finished. Вывод в qDebug() и посмотрите - может у вас readAll не справляется. А кроме того
QString QTextStream::readAll ()
Reads the entire content of the stream, and returns it as a QString. Avoid this function when working on large files, as it will consume a significant amount of memory.
Calling readLine() is better if you do not know how much data is available.
Попробуйте обработать и finished. Вывод в qDebug() и посмотрите - может у вас readAll не справляется. А кроме тогоQString QTextStream::readAll ()
Reads the entire content of the stream, and returns it as a QString. Avoid this function when working on large files, as it will consume a significant amount of memory.
Calling readLine() is better if you do not know how much data is available.
Благодарю за совет, при случае попробую, но сейчас я QTextStream не использую,
а у QTcpSocket этого сигнала нет.
Пётр.