Название: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Август 24, 2012, 17:43 Хочу реализовать своей простой протокол для отправки данных типа
Отправка Код: _sok = new QTcpSocket(); Прием Код: void MyThread::readyRead() То есть если кликать то картина в начале и в конце картина будет такая Цитировать bytesAvailable 7 Как бы передать весь цикл за одно нажатие кнопки?size 5 bytes "0" ... bytesAvailable 581 size 5 bytes "7" ... bytesAvailable 73163 size 7 bytes "783" Если использовать _sok->write(QByteArray file) то например файл 300Мб передается нормально, write все делает сам, но так ничего нельзя дописать в пакет. Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Август 30, 2012, 16:26 Видимо QT сворачивается и скоро станет не актуальным поскольку перешел к другом хозяину, по этому все побежали на новую VS и .Net.
Жаль. Название: Re: QTcpSocket не успевает принять пакеты отправленнm Отправлено: mutineer от Август 30, 2012, 16:41 зачем писать размер отправленного пакета, если не проверять его при приеме?
Ты вычитываешь только первую посылку, хотя доступно для чтения (судя по bytesAvailable) больше Про какие нажатия кнопки ты говоришь я вообще не понял Название: Re: QTcpSocket не успевает принять пакеты отправленнm Отправлено: voron1980 от Сентябрь 03, 2012, 14:21 зачем писать размер отправленного пакета, если не проверять его при приеме? Но пакеты тем не менее теряются, никак не могу найти нормальный бесплатный sniffer под Windows без WinPcap, что бы посмотреть содержимое пакетов и их количество, может кто подскажет?Ты вычитываешь только первую посылку, хотя доступно для чтения (судя по bytesAvailable) больше Про какие нажатия кнопки ты говоришь я вообще не понял Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: mutineer от Сентябрь 03, 2012, 14:41 С чего ты взял что пакеты теряются? судя по выводу они висят себе на принимающей стороне, а ты их не вычитываешь
Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 03, 2012, 16:12 С чего ты взял что пакеты теряются? судя по выводу они висят себе на принимающей стороне, а ты их не вычитываешь Да они висели, но это удалось понять только после того как я проверил пакеты снифером "SoftPerfect Network Protocol Analyzer" вроде бесплатный есть портайбл версия, хватило с головой, но пришлось сервер запустить на отдельной машине, сниффер не следит за пакетами отправленными с хоста на самого себя, какой бы IP у него не стоял.Оказывается в пакет кладется не один набор данных in >> size; in >> bytes; а сколько влезет, тогда сразу начал искать как пройтись по socket циклом и нашел http://qt-project.org/forums/viewthread/3587 Код: connect(socket, SIGNAL(readyRead()), SLOT(newData())); Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: fuCtor от Сентябрь 03, 2012, 16:19 Не совсем корректная проверка. Из-за фрагментации при запросе может быть не весь набор данных получен => может быть считано все не полнотью, что может привести к дальнейшей некорректной работе. Нужно проверять доступно ли байт столько, сколько потребуется для корректного вычитывания структуры\пакета.
Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: mutineer от Сентябрь 03, 2012, 16:49 Да они висели, но это удалось понять только после того как я проверил пакеты снифером "SoftPerfect Network Protocol Analyzer" То есть простого факта, что доступно для чтения 73163 байта, а читаешь ты только 7 недостаточно, чтобы понять что оставшееся так и висит в буфере? Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: fuCtor от Сентябрь 03, 2012, 18:18 Да они висели, но это удалось понять только после того как я проверил пакеты снифером "SoftPerfect Network Protocol Analyzer" То есть простого факта, что доступно для чтения 73163 байта, а читаешь ты только 7 недостаточно, чтобы понять что оставшееся так и висит в буфере? В определенный момент времени там может оказаться допустим 3 байта, вероятность такой ситуации не такая уж маленькая. Тогда тело цикла (допустим чтение int32) отработает в лучшем случае некорректно и не вызовет падения, да буфер опустошен, но придет новый пакет и в нем будет один лишний байт, как результат как читать и обрабатывать данные? Правильней проверить как уже писал доступность именно того объема который нужен для обработки, а не просто доступность, и только потом его вычитывать, иначе подождать нового пакета, либо сохранить что есть во внутренний буфер. Если я не прав, то поправьте меня. Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 03, 2012, 22:51 Не совсем корректная проверка. Из-за фрагментации при запросе может быть не весь набор данных получен => может быть считано все не полнотью, что может привести к дальнейшей некорректной работе. Нужно проверять доступно ли байт столько, сколько потребуется для корректного вычитывания структуры\пакета. Проверки никакой нет, просто данные считываются в том порядке в котором пришли, это подтверждают разные статьи, QDataStream контролирует порядок отправки и приема.Но похоже если файл больше 2 мегабайт начинаются проблемы с целостностью, 9Мб уже битый. Если склеивать куски файла в цикле нарезки(эти же куски пишутся в сокет) то файл склеивается нормально, а вот к серверу доходят не все данные, притом чем больше больше данных ушло тем ниже скорость, на 1,5Гб скорость по локальному интнрфейсу всего 200кб в секунду что очень мало, возможно виноват вывод через qDebug() <<. Поскольку TCP протокол сам контролирует целостность то это похоже баг. Еще раз, проверка сколько байт пришло ничего не даст, все проверяется на уровне QDataStream именно по этому я и заинтересовался темой, склеивать байты в ручную это очень трудоемкая работа. Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: mutineer от Сентябрь 04, 2012, 10:10 Если я не прав, то поправьте меня. Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 04, 2012, 11:28 Если я не прав, то поправьте меня. Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги Название: Re: QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: mutineer от Сентябрь 04, 2012, 11:29 Если я не прав, то поправьте меня. Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги Что? Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 04, 2012, 13:17 Нет идей почему данные иногда искажаются?
Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: lighting от Сентябрь 04, 2012, 14:39 Нет идей почему данные иногда искажаются? Видимо не все считываете. А вообще код выложить не помешало-бы, или он у вас с первого поста не менялся?Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 04, 2012, 15:31 Нет идей почему данные иногда искажаются? Видимо не все считываете. А вообще код выложить не помешало-бы, или он у вас с первого поста не менялся?Вот пример нужно только в переменные wFName и rFName прописать пути файлов которые будут считываться и записываться, wFName1 нужен для проверки, что бы сравнивать каким должен был быть файл и wFName как его перекосило отправкой. После отключения wFName1 стирается на диске. При передаче по сети 9Мб файл не всегда битый, а вот 78Мб например всегда, и если я кидаю в память то данных теряется меньше, а если писать сразу на диск то из 78Мб теряется ~1Мб если через буфер то теряется примерно ~200Кб. Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: fuCtor от Сентябрь 04, 2012, 18:32 Посмотрел код, не знаю может так и можно, но учитывая что сокеты используются асинхронные, то в таком же стиле нужно и читать/отправлять данные (так будет надежней), возможно где-то недочитывали данные, либо недосылали.
Переписал в клиенте и сервере эти части, сделал полностью асинхронными. Проверил на файле в 88Мб, после приема сверил контрольные суммы, все сошлось. Клиент: Код
Сервер: Код
Исправленную версию с комментариями прикладываю. Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 04, 2012, 23:53 Спасибо попробую!
----- Протестировал работает! Думал использовать QDataStream для передачи приемки, в общем завтра на свежую голову попробую разобраться. Главное есть маркер и можно понять что за пакет если я не ошибаюсь. P.S. К стати если кто будет смотреть пример нужно в конфигурации проекта удалить конфигурацию там где пути к среде компилятора и добавить званого, то что предложит IDE по умолчанию, а затем добавить вариант сборки, иначе проект не запускается, это наверное так всегда если обмениваться проектами, в общем в первой закладке проекта все решается. Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: voron1980 от Сентябрь 05, 2012, 17:59 То что надо, отличная заготовка для обмена данными без лишних наворотов.
Код: QObject::setProperty() Еще раз спасибо. Название: Re: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while. Отправлено: fuCtor от Сентябрь 06, 2012, 15:51 То что надо, отличная заготовка для обмена данными без лишних наворотов. Код: QObject::setProperty() Еще раз спасибо. Да, если объектов (например сокетов) открытых более одного, то как вариант можно хранить связанные указатели в свойствах, что-бы не использовать массивы/таблицы. Единственное, для большей надежности, после создания экземпляра QFile, лучше ему еще присвоить родителем сокет, что-бы при удалении сокета (где-нибудь раньше времени) удалились и все связанные объекты во избежание утечек. |