|
1 / 1 / 0
Регистрация: 25.04.2015
Сообщений: 26
|
|
Потоки, QSeriaport, QTcpserver (Алгоритм чтения/отправки данных)08.03.2016, 14:31. Показов 6106. Ответов 66
Метки нет (Все метки)
Здравствуйте, уважаемые жители кибер форума. Обращаюсь за консультацией.
Вопрос в следующем. Есть устройство на чипе PIC18F2550, которые шлет пакеты по COM порту. (длина пакетов 10-30 байт, максимально возможное кол-во пакетов в секунду 300-500). Пишу софт, для работы с данным устройством. Требования к функционалу следующие: Читать данные с устройства, записать эти данные в файл и отправить эти данные ко всем, кто подключен к сокету, если никого на сокете нет - не отправлять. Есть сигнал (ReadyRead), т.е. как только устройство готово что-то передать, вызывается некоторый слот, в котором данные считываются функцией ReadLine() или ReadAll(). Далее, в этой функции: если в GUI чекбокс нажат, происходит вызов функции writeBin, в качестве аргумента ей передается полученный с устройства QByteArray (происходит запись полученных данных в файл). По моей идее необходимо сделать еще одну функцию (Функция отправки по сети), которой в качестве аргумента передается тот же массив полученных с устройства QByteArray. Теперь вопросы. Как сделать алгоритм чтения/записи/отправки так, чтобы не пострадал прием данных с устройства. И вообще как ведут себя сигналы в данном случае? Т.е. получил сигнал ReadyRead о том, что ожидают чтения с устройства байты, начинается выполняться слот по чтению данных. И тут подключатся клиент (вызывается сигнал NewConnection). Управление с функции readyRead передается слоту, который срабатывает при сигнале NewConnection. Соответственно чтение с устройства прерываются до тех пор, пока не отработает newconnection либо пока не придет новый сигнал ReadyRead. Это вопрос номер 1. И вопрос номер 2. Например все хорошо, и у нас 2 клиента. Если писать процедурно, то для отправки двум клиентам функция будет вызываться 2 раза. Ну или один раз (зациклить по кол-во соединенных сокетов). Так вот в чем беда, с приемника данные продолжают сыпаться. И пока функция не отправит предыдущие данные, чтение новых не происходит чтоли? На правильность идеи не претендую. Любая критика приветствуется.
0
|
|
| 08.03.2016, 14:31 | |
|
Ответы с готовыми решениями:
66
Алгоритм чтения данных из памяти Алгоритм чтения текстового файла в массив данных открытого типа Потоки чтения и записи. |
|
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
|
|
| 13.04.2016, 20:15 | |
|
Avazart, если нет я вас ни в чем убеждать не собираюсь. Но мой совет остается в силе. Наследование потоков в данном случае is not Qt way. И глупо это использовать классы и методы так, что потом приходится плодить костыли и отлавливать ошибки.
https://blog.qt.io/blog/2010/0... /#comments My #1 biggest gripe with this code is moveToThread(this); I see so many people using this without understanding what it does. What does it do, you ask? The moveToThread() function tells Qt to ensure that event handlers, and by extension signals and slots, are called from the specified thread context. QThread is the thread interface, so we’re telling the thread to run code “in itself”. We’re also doing this before the thread is running as well. Even though this seems to work, it’s confusing, and not how QThread was designed to be used (all of the functions in QThread were written and intended to be called from the creating thread, not the thread that QThread starts). My impression is that moveToThread(this); creeps into people’s code because they saw some blog somewhere that used it. A quick web search turns up several of these blogs, all of which follow the pattern in the class above: subclass QThread add signals and slots to do work test code, see that the slots aren’t called “from the right thread” ask google, find moveToThread(this); and comments that “it seems to work when I add this” In my opinion, the problems started at step 1. QThread was designed and is intended to be used as an interface or a control point to an operating system thread, not as a place to put code that you want to run in a thread. We object-oriented programmers subclass because we want to extend or specialize the base class functionality. The only valid reasons I can think of for subclassing QThread is to add functionality that QThread doesn’t have, e.g. perhaps providing a pointer to memory to use as the thread’s stack, or possibly adding real-time interfaces/support. Code to download a file, or to query a database, or to do any other kind of processing should not be added to a subclass of QThread; it should be encapsulated in an object of it’s own. Usually, this means simply changing your class to inherit from QObject instead of QThread and, possibly, changing the class name. QThread has a started() signal that you can connect to when you need to perform some initialization. To actually have your code run in the new thread context, you need to instantiate a QThread and assign your object to that thread using the moveToThread() function. Even though you are still using moveToThread() to tell Qt to run your code in a specific thread context, we are keeping the thread interface separate. If necessary, it is now possible to have multiple instances of your class assigned to a single thread, or multiple instances of many different classes assigned to a single thread. In other words, it’s unnecessary to tie a single instance of a class to a single thread.
0
|
|
|
|
||||||||
| 13.04.2016, 20:30 | ||||||||
0
|
||||||||
|
68 / 68 / 17
Регистрация: 20.01.2015
Сообщений: 347
|
|
| 13.04.2016, 22:19 | |
|
Avazart, Это "мнение" далеко не только мое личное - это общедоступное мнение, подкрепленное официальным заявлением разработчика. До тех пор пока вы не находитесь в команде разработчиков Qt, извините, это именно ваше мнение, что считать глупым, а что нет - остается не более чем чисто вашим личным мнением. Можете остаться при нем, я на него не претендую. В конце концов, я не стараюсь переубедить весь мир что делать правильно, а что нет - у каждого есть право оставаться в своих заблуждениях. На чем основан мой совет - я обосновал. За сим откланиваюсь. Разговаривать со стенами считаю пустой тратой времени, которого у меня и так не много.
0
|
|
|
|
|||
| 14.04.2016, 07:07 | |||
|
Amok, за 5 лет концепция использования потоков смягчилась, хотя, учитывая, что сорцы потоков за это время не менялись сколь-нибудь значительно, совет ещё актуален.
Avazart, вооброжением вы руководствуетесь и памятью о Qt3. Проснитесь и пойте, мистер Avazart, проснитесь и пойте. http://doc.qt.io/qt-5/qthread.html#details
0
|
|||
|
|
||||
| 14.04.2016, 18:28 | ||||
|
Где там написано не используйте наследование? И вы предполагаете в оставшихся 25% лепить горбатого? Трактовать про отказ тут нельзя ну никак. В приведенном тексте лишь описание того как оно работает и что из этого следует. Напротив там же в доке читаем:
(до этого был приведен пример с передачей "рабочего" объекта) Добавлено через 3 минуты
0
|
||||
|
|
|||||
| 14.04.2016, 20:50 | |||||
|
Avazart, да ладно тебе, перестань строить из себя всезнающего говнюка и признай, что для новичка наследование QThread - ошибочный сценарий использования потоков. Иначе этой темы бы не было.
Добавлено через 10 минут
0
|
|||||
|
|
|||
| 14.04.2016, 21:06 | |||
|
С таким же успехом можно накосячить с передачей "рабочего" объекта, к примеру в конструкторе "рабочего" класса создать сериал порт или сокет, но забыть передать во владения this. Речь была о " Кстати если не ошибаюсь у ТС был нормальный код. Проблема не в подходе к потокам, а в общей структуре программы, работе с сетью.
0
|
|||
|
|
||||
| 15.04.2016, 07:05 | ||||
|
Зачем? Религия.
0
|
||||
|
|
||||
| 15.04.2016, 12:52 | ||||
|
И тут явно без потоков не обойтись, если хочется сделать по нормальному. И не важно какой подход, весь вопрос в том как вообще какая логика.
0
|
||||
|
|
|||||
| 15.04.2016, 13:07 | |||||
|
Avazart, серьёзно, можно сколько угодно пытаться сказать "а вдруг то, а вдруг это", к делу это не относится до тех пор, пока об этом не написали явно. В данный момент нет проблем со скоростью работы, как только появятся, все подходящие советы будут даны. Есть проблема с тем, что наследование потоков работает неприемлимо. Так что признайтесь, вам просто не нравится, что люди советуют делать рабочих и перемещать их в поток, соединяя сокетами, и вы каждый божий раз будете цеплять тех, кто советует покупать рабов, а не наследовать потоки. Как только мы дойдём до признания догм, они станут необсуждаемыми - и спор будет исчерпан. Не по теме: android52, извини за срач.
0
|
|||||
|
|
||||
| 15.04.2016, 13:29 | ||||
|
0
|
||||
|
|
|
| 15.04.2016, 13:46 | |
|
Avazart, до сих пор не советую. Сейчас далеко не очевидно, что обработка данных является узким местом, а все IO-классы имеют внутри по потоку, поэтому вынесение их ещё куда-то избыточно до тех пор, пока не доказано обратное.
0
|
|
|
|
||
| 15.04.2016, 14:00 | ||
|
Да обработка данных почти всегда узкое место. В данном случае как минимум есть запись в файл:
Тут может быть по разному, как я и говорил нужно видеть всю логику.
0
|
||
|
1 / 1 / 0
Регистрация: 25.04.2015
Сообщений: 26
|
||||||
| 20.04.2016, 21:37 [ТС] | ||||||
|
Битва программистов
![]() Вообщем-то, как кто-то написал про отдельный класс и все такое.. Я использую объектно-ориентированную модель.. Мне так удобнее. Каждый класс выполняет свои задачи. То, что приводил на форуме набросано на скорую руку ради тестов, чтобы не засорять проект мыслями. По поводу логики. Для начала планирую сделать так: Есть класс tcpserver, условно назовем его швейцаром . У него есть обязанности: встречать/провожать клиентов, говорить клиентам. Некоторые особенности: швейцар говорит только за одним столом и сразу всем клиентам (ему лень говорить одно и тоже каждому из клиентов). Как только приходит клиент, он провожает его за единственный стол. Есть класс serial. Условно назовем его администратором. Администратор от директора получает сообщения. Его задача передать все сообщения швейцару, чтобы последний все передал клиентам. Обязанности: сказать сообщение швейцару. -------------------------- Как только приходит новый клиент, швейцар усаживает его за стол (записывает в карту), в тоже время швейцар получает сообщения от администратора. Если за столом есть хоть один клиент, швейцар начинает говорить сообщения, получаемые от администратора. Если клиент уходит, швейцар его провожает (удаляет из карты). Проблема №1. Мой швейцар не швейцар. Не хочет провожать клиентов (не удаляет из карты). Реализация:
Проблема №2. Сообщения которые шлет администратор необходимо каким-то образом отделить друг от друга. Не то у швейцара каша будет в голове. Подробнее ниже. Администратор получает сразу много сообщений. (скорость 3 мбит/с). Каждое сообщение начинается с байта 0x3F и далее сообщение. Сообщение имеет разную длину. Если в сообщении встречается байт 0x3F то данный байт повторяется, дабы, чтобы администратор не спутал его с началом нового сообщения. Еще администратор может получить 1,5 сообщения, а остальные 0,5 будут в следующей посылки. Кто подскажет? как построить логику разбивки данных сообщений, чтобы 0,5 предыдущего не терялось...
0
|
||||||
|
|
|
| 20.04.2016, 21:56 | |
|
Проблема 1 решается так, как я описал ранее. Один раз посчитали и отправили сигналом. Все подписчики получат, если есть. Скорость не страшная. Другой вопрос, у вас действительно широковещательные сообщения или нет?
В любом случае, tcpServer это швейцар, а вы его ещё и в крупье записали. Швейцар просто должен провожать клиентов до стола, дальше не его работа. А вот крупье уже раздаёт карты. Проблема 2: Если можете изменить протокол, меняйте. Почитайте, только, любую книжку по сетям. Если коротко, начинайте сообщение с его размера, дальше тип, затем само сообщение, далее по желанию.
0
|
|
|
1 / 1 / 0
Регистрация: 25.04.2015
Сообщений: 26
|
|
| 20.04.2016, 22:17 [ТС] | |
|
icpu, протокол изменить не вариант. Повторюсь, размер пакета всегда разный. Сети здесь не причем. Я с устройства получаю 2,5 сообщения например. За одну передачу в сеть нужно послать одно сообщение. Логично. что сначала пакеты нужно отделить друг от друга. Сделать какой-нибудь буфер программный. Есть только признак нового пакета байт 0x3f. Если данный байт встречается в теле сообщения, то он повторяется, например:
3F5D33321A - посылка с устройства без повторений 0x3F 3F5D3F3F1A - в теле сообщения встретился байт начало пакета. Чтобы не перепутать с началом нового пакета устройство добавляет после 3f еще один 3f. Добавлено через 2 минуты icpu, Нет, сообщения не широковещательные. Их слушаю только те, кому они нужны
0
|
|
| 20.04.2016, 22:17 | |
|
Потоки С++.Файл не открывает себя для чтения. Алгоритм отправки формы
Алгоритм отправки файла на почту Алгоритм получения и отправки reCaptcha Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
|
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#.
Название изменил на ColorStep.
Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
|
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами:
- ВидТО (СправочникСсылка. ВидыТО);
- ВидГСМ. . .
|
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала.
Ниже прикреплён. . .
|
|
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F
Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU.
Опрашиваются регистры. . .
|
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка:
Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
|
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо
Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
|
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман.
Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
|