Russian Qt Forum
Ноябрь 23, 2024, 19:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [РЕШЕНО]QTcpSocket не успевает принять пакеты отправленные в теле цикла while.  (Прочитано 12406 раз)
voron1980
Гость
« : Август 24, 2012, 17:43 »

Хочу реализовать своей простой протокол для отправки данных типа
Отправка
Код:
    _sok = new QTcpSocket();
    int i = 0;
    while(true)
    {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out << (qint16)0;
        out << (QByteArray) QByteArray::number(i);
        out.device()->seek(0);
        out << (quint16)(block.size() - sizeof(quint16));
        _sok->waitForBytesWritten();
        i++;
        if(i > 1000)
            break;
    }

   
Прием
Код:
void MyThread::readyRead()
{    
    QDataStream in(socket);
    qint16 size;
    in >> size;
    qDebug() << "size" << size;
    QByteArray bytes;
    in >> bytes;
    qDebug() << "bytes" << bytes;
    bytes.clear();
}
После приема данных получается что цикл идет допустим 260 раз а потом останавливается, но когда я не отключаясь отправляю еще данные то цикл продолжается, то есть данные которые небыли отправлены отправляются при следующем клике, при этом добавляются новые данные, получается в очередь на отправку стоит в несколько раз больше данных чем передается.
То есть если кликать то картина в начале и в конце картина будет такая
Цитировать
bytesAvailable 7
size 5
bytes "0"
...
bytesAvailable 581
size 5
bytes "7"
...
bytesAvailable 73163
size 7
bytes "783"
Как бы передать весь цикл за одно нажатие кнопки?
Если использовать _sok->write(QByteArray file) то например файл 300Мб передается нормально, write все делает сам, но так ничего нельзя дописать в пакет.
« Последнее редактирование: Сентябрь 03, 2012, 16:13 от voron1980 » Записан
voron1980
Гость
« Ответ #1 : Август 30, 2012, 16:26 »

Видимо QT сворачивается и скоро станет не актуальным поскольку перешел к другом хозяину, по этому все побежали на новую VS и .Net.
Жаль.
Записан
mutineer
Гость
« Ответ #2 : Август 30, 2012, 16:41 »

зачем писать размер отправленного пакета, если не проверять его при приеме?
Ты вычитываешь только первую посылку, хотя доступно для чтения (судя по bytesAvailable) больше

Про какие нажатия кнопки ты говоришь я вообще не понял
« Последнее редактирование: Август 30, 2012, 16:44 от mutineer » Записан
voron1980
Гость
« Ответ #3 : Сентябрь 03, 2012, 14:21 »

зачем писать размер отправленного пакета, если не проверять его при приеме?
Ты вычитываешь только первую посылку, хотя доступно для чтения (судя по bytesAvailable) больше

Про какие нажатия кнопки ты говоришь я вообще не понял
Но пакеты тем не менее теряются, никак не могу найти нормальный бесплатный sniffer под Windows без WinPcap, что бы посмотреть содержимое пакетов и их количество, может кто подскажет?
Записан
mutineer
Гость
« Ответ #4 : Сентябрь 03, 2012, 14:41 »

С чего ты взял что пакеты теряются? судя по выводу они висят себе на принимающей стороне, а ты их не вычитываешь
Записан
voron1980
Гость
« Ответ #5 : Сентябрь 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()));
....
void newData()
{
     while(socket->bytesAvailable())
    {
         QDataStream in(socket);
         QString str;
         in >> str;
         ....
    }
....
}
Записан
fuCtor
Гость
« Ответ #6 : Сентябрь 03, 2012, 16:19 »

Не совсем корректная проверка. Из-за фрагментации при запросе может быть не весь набор данных получен => может быть считано все не полнотью, что может привести к дальнейшей некорректной работе. Нужно проверять доступно ли байт столько, сколько потребуется для корректного вычитывания структуры\пакета.
Записан
mutineer
Гость
« Ответ #7 : Сентябрь 03, 2012, 16:49 »

Да они висели, но это удалось понять только после того как я проверил пакеты снифером "SoftPerfect Network Protocol Analyzer"

То есть простого факта, что доступно для чтения 73163 байта, а читаешь ты только 7 недостаточно, чтобы понять что оставшееся так и висит в буфере?
Записан
fuCtor
Гость
« Ответ #8 : Сентябрь 03, 2012, 18:18 »

Да они висели, но это удалось понять только после того как я проверил пакеты снифером "SoftPerfect Network Protocol Analyzer"

То есть простого факта, что доступно для чтения 73163 байта, а читаешь ты только 7 недостаточно, чтобы понять что оставшееся так и висит в буфере?
Мы хотим сделать программу которая тупо вичитывает данные из буфера или программу, которая выполняет корректно заложенную логику?

В определенный момент времени там может оказаться допустим 3 байта, вероятность такой ситуации не такая уж маленькая. Тогда тело цикла (допустим чтение int32) отработает в лучшем случае некорректно и не вызовет падения, да буфер опустошен, но придет новый пакет и в нем будет один лишний байт, как результат как читать и обрабатывать данные?

Правильней проверить как уже писал доступность именно того объема который нужен для обработки, а не просто доступность, и только потом его вычитывать, иначе подождать нового пакета, либо сохранить что есть во внутренний буфер.
Если я не прав, то поправьте меня.
Записан
voron1980
Гость
« Ответ #9 : Сентябрь 03, 2012, 22:51 »

Не совсем корректная проверка. Из-за фрагментации при запросе может быть не весь набор данных получен => может быть считано все не полнотью, что может привести к дальнейшей некорректной работе. Нужно проверять доступно ли байт столько, сколько потребуется для корректного вычитывания структуры\пакета.
Проверки никакой нет, просто данные считываются в том порядке в котором пришли, это подтверждают разные статьи, QDataStream контролирует порядок отправки и приема.
Но похоже если файл больше 2 мегабайт начинаются проблемы с целостностью, 9Мб уже битый.
Если склеивать куски файла в цикле нарезки(эти же куски пишутся в сокет) то файл склеивается нормально, а вот к серверу доходят не все данные, притом чем больше больше данных ушло тем ниже скорость, на 1,5Гб скорость по локальному интнрфейсу всего 200кб в секунду что очень мало, возможно виноват вывод через qDebug() <<.
Поскольку TCP протокол сам контролирует целостность то это похоже баг.
Еще раз, проверка сколько байт пришло ничего не даст, все проверяется на уровне QDataStream именно по этому я и заинтересовался темой, склеивать байты в ручную это очень трудоемкая работа.
« Последнее редактирование: Сентябрь 03, 2012, 23:42 от voron1980 » Записан
mutineer
Гость
« Ответ #10 : Сентябрь 04, 2012, 10:10 »

Если я не прав, то поправьте меня.


Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги
Записан
voron1980
Гость
« Ответ #11 : Сентябрь 04, 2012, 11:28 »

Если я не прав, то поправьте меня.


Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги
Ну вы же написали в теме, может вы ошиблись?
Записан
mutineer
Гость
« Ответ #12 : Сентябрь 04, 2012, 11:29 »

Если я не прав, то поправьте меня.


Какое я имею отношение к правильности/неправильности считывания? Я указал на то, что местоположение "потерянных" пакетов видно без сниффера, просто по выводу проги
Ну вы же написали в теме, может вы ошиблись?

Что?
Записан
voron1980
Гость
« Ответ #13 : Сентябрь 04, 2012, 13:17 »

Нет идей почему данные иногда искажаются?
Записан
lighting
Гость
« Ответ #14 : Сентябрь 04, 2012, 14:39 »

Нет идей почему данные иногда искажаются?
Видимо не все считываете. А вообще код выложить не помешало-бы, или он у вас с первого поста не менялся?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.056 секунд. Запросов: 21.