LinuxForum.Fans
Тема

QTcpSocket->read()

Автор: Peter 35 сообщений 6801 просмотров
#280222

Здравствуйте!

Есть программа сервер на одном компьюетер и программа-клиент на другом,
обе на Qt, общаются по сети. Кроме постоянно идущих данных, клиент иногда
получает от сервера команды в виде массива из 8 байтов, QTcpServer передаёт,
а QtcpSocket принимает, другие, чем для предачи данных. Клиент в Ubuntu-11.04,
сервер в Ubuntu 10.04, Qt-4.7.x.

Несмотря на маленький размер команды, клиент иногда получает ложные команды,
которых сервер не посылал. Конкретно, запускается клиент, сервер тут же
посылает ему команду, затем по щелчку мыши другую, она принимается и
исполняется правильно, но затем клиент принимает ещё 8 байтов, непонятно отчего.

Я пробовал в клиенте вызывать waitForReadyRead(timeout) перед read(), либо использовать
readAll() и проверять, что пришли все 8 байтов. Это помогает при передаче и приёме
больших посылок - jpg-файлов, но в случае с командой не помогло, всё равно
получаются лишние 8 байтов. В чём причина и как бороться, м.б., кто-нибудь знает?

Пётр.

#280224
Peter написал:
программа сервер на одном компьюетер и программа-клиент на другом

А что за программа и как проверить что происходит её не имея? Примерно так:

#280262

Там нечего проверять - с одной стороны write(), с другой read(),
а что происходит, я рассказал. После приёма посланной команды якобы принимаются
ещё раз 8 байтов.

Пётр.

#280269

Что то в памяти в этом плане все зашорено.... Сейчас нет времени воскрешать.
Если не ошибает память могут быть проблемы связанные с выравниванием.

#280298

Там есть разница в условиях при передаче первых двух команд, принимающихся правильно и 3-ей,
принимающейся неправильно. После 2-й команды по тому же кабелю клиент начинает получать
jpg-файлы с частотой 10 раз в секунду, через другой сокет, а до этого линия свободна. Однако 3-я
команда стабильно приходит с одними и теми же ошибками, 2-й и 6-й байты.

Пётр.

#280337
Peter написал:
Там нечего проверять - с одной стороны write(), с другой read(),
а что происходит, я рассказал. После приёма посланной команды якобы принимаются
ещё раз 8 байтов.

Пётр.

В любую передачу данных по протоколу TCP необходимо первым делом засовывать размер передаваемого блока.
К примеру:
QByteArray out;
out << quint16(0);
out << "суем данные"
out << "в первые два байта засовываем out.size();"

На стороне клиента, читаем первые два байта(определяем как размер сообщения) и ждем прима.

#280341
marikk написал:
[quote=Peter]Там нечего проверять - с одной стороны write(), с другой read(),
а что происходит, я рассказал. После приёма посланной команды якобы принимаются
ещё раз 8 байтов.

Пётр.

В любую передачу данных по протоколу TCP необходимо первым делом засовывать размер передаваемого блока.
К примеру:
QByteArray out;
out << quint16(0);
out << "суем данные"
out << "в первые два байта засовываем out.size();"

На стороне клиента, читаем первые два байта(определяем как размер сообщения) и ждем прима.[/quote]
Несколько месяцев назад я так делал, но тогда размер передаваемого массива был заранее неизвестен.
Если вы имеете в виду именно протокол TCP, то я же сам не подготавливаю его заголовок, это делает Qt.
Такой небольшой масссив - 8 байтов - должен передаваться за один раз. Конкретно, в 3-й раз посылается

text
1 3 2 0 1 0 -1 -1

а принимается всегда

text
1 1 2 0 1 -1 -1 -1

тогда как предидущая посылка, после приёма которой клиент начинает получать jpg от сервера через
другой сокет, принимается правильно:

text
1 3 2 0 1 -1 -1 -1

Пётр.

#280343

Не глядя в исходники трудно гадать. Такое ощущение, что у вас вообще проблема не там где ищите.
Попробуйте передать во второй заход:

1 2 3 4 5 6 7 8

А в третий
11 12 13 14 15 16 17 18

И посмотреть что приходит

#280428

Если бы я знал, в чём проблема, то, наверное, нашёл бы способ её обойти.
Похоже, что неправильный приём команды начинается после того, как клиент
по 2-й команде начинает принимать jpg от того же сервера по тому же
интерфейсу. Но, возможно, попробую передать 3-ю команду произвольную.

Пётр.

#280436
"Peter" написал:
Похоже, что неправильный приём команды начинается после того, как клиент
по 2-й команде начинает принимать jpg от того же сервера по тому же
интерфейсу.

Не понял.

У вас установлено одно соединение между клиентом и сервером?
Третья команда отправляется сервером и одновременно передается jpg?
Как у вас организовано какие байты и к чему относятся?

Или у вас третья команда идет уже после приема jpg?

#280437
"Peter" написал:
Если бы я знал, в чём проблема, то, наверное, нашёл бы способ её обойти.

А я и не предлагаю обойти. Я пытаюсь прикинуть где у вас может быть ошибка.

Вы не можете выкусить минимальный кусок кода, что б ни чего лишнего, но происходило именно так как происходит?

#280472
voral написал:
[quote="Peter"]Похоже, что неправильный приём команды начинается после того, как клиент
по 2-й команде начинает принимать jpg от того же сервера по тому же
интерфейсу.

Не понял.

У вас установлено одно соединение между клиентом и сервером?
Третья команда отправляется сервером и одновременно передается jpg?
Как у вас организовано какие байты и к чему относятся?

Или у вас третья команда идет уже после приема jpg?[/quote]
Да, 3-я команда посылается клиенту после того, как он по 2-й начал приём jpg и я это говорил.
По 2-й команде он связывается с сервером через другой сокет и другой порт и
начинает через него получать jpg, т.е два соединения, но один интерфейс eth.
Т.е. для получения команд используется одна тройка сервер-сокет-порт, а для получения
jpg - другая и jpg идут 10 раз в секунду.
При этом передача jpg и команд никак не синхронизированы. М.б., использовать mutex,
чтобы не было наложения? Но ведь протокол TCP и так обязан обеспечивать доставку пакетов.

Пётр.

#280490
"Peter" написал:
При этом передача jpg и команд никак не синхронизированы. М.б., использовать mutex,
чтобы не было наложения? Но ведь протокол TCP и так обязан обеспечивать доставку пакетов.

не. Дело точно не в TCP.
Это работает в разных потоках?

#280493
voral написал:
[quote="Peter"]При этом передача jpg и команд никак не синхронизированы. М.б., использовать mutex,
чтобы не было наложения? Но ведь протокол TCP и так обязан обеспечивать доставку пакетов.

не. Дело точно не в TCP.
Это работает в разных потоках?[/quote]
Да, для получения jpg создаётся отдельный поток и их может быть до четырёх.
Это работает, но раньше такие потоки создавались не по одному, а сразу, сколько надо,
по команде, котрую я здесь назвал 2-й. jpg от них принимает одна функция на всех,
но сейчас запускается только один поток.

Пётр.

#280494

Можете "отключить" передачу jpg. Пусть просто идет та череда команд, что должна идти.

#280495

Начинайте отключать по максимуму функционал не относяящийя непосредственно к передаче и приму команд

#280502
voral написал:
Можете "отключить" передачу jpg. Пусть просто идет та череда команд, что должна идти.

Тогда нечего будет проверять. Ведь первые две команды, пока не запущен прием jpg,
принимаются правильно, а неправильно принимается 3-я. Можно будет проверить разве,
как пройдёт 3-я команда, если она будет не на запуск нового потока, как сейчас,
а на закрытие уже запущенного.
Программа ничего не делает кроме того, что принимает jpg, декодирует их и выводит на экран.
Для неё является нормальным, когда при этом приходят команды. Команды, кроме 1-й,
посылаются по щелчку мыши.

Пётр.

#280524

Попробовал дать 3-ю команду на остановку потока:

text
1 3 2 0 -1 -1 -1 -1

пришло то же самое, что и при команде запуска нового:

text
1 1 2 0 1 -1 -1 -1

откуда оно берётся, непонятно.

Пётр.

#280554

Можете рассказать подробнее об этих 8 байтах.

- Какова их структура (хотя бы каждый байт самостоятельная величина, или некоторые величины имеют размер больше байта).
- как вы работаете с этими байтами (просто массив, струтура ....)
- как анализируете значения (например операции логические сравнения или просто условные)....

#280576

voral написал:
Можете рассказать подробнее об этих 8 байтах.

- Какова их структура (хотя бы каждый байт самостоятельная величина, или некоторые величины имеют размер больше байта).
- как вы работаете с этими байтами (просто массив, струтура ....)
- как анализируете значения (например операции логические сравнения или просто условные)....
\
Не понял, что от меня требуется. Все величины по размеру укладываются в байт, сам массив для их приёма - char.
Отладочная печать есть на обеих сторонах, из сервера посылаемый массив печатается правильно, в клиенте
сразу после приёма 3-й команда печатается неправильно. Наверное, что-то я делаю неправильно, но не пойму что.
По этому соединению передаются только команды.

Рётр.
Войдите или зарегистрируйтесь, чтобы ответить.