Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Как реализовать прием пакета неопределеной длины?


Автор: LeonidPr 20.3.2012, 10:03
В микроконтроллерах данная задача решается достаточно просто. Считается количество тиков аппаратного таймера, прошедших с момента приема последнего байта. Если это количество превысило некоторый лимит, то считаем, что принятые на этот момент байты - и есть весь пакет, далее идет его обработка, это уже дело техники.
Как реализовать подобный алгоритм работы в windows?
Немного объясню причину возникновения вопроса.
Не раз приходилось писать простенькие программы для опроса конкретных устройств по ModBus. Обычно, в таком случае, отсылая запрос я уже знал размер ответа и считывал из порта нужное количество байт. При настроенных таймаутах, если пришло слишком мало байт (пакет оборван) обрабатывалась ошибка, если все нормально - обрабатывался ответ. Это работало, для тех программ большего было не нужно. Но это работает, если мы заранее знаем размер принимаемого пакета. А если нет? Хотелось бы сделать так: пришел пакет ответа, я его обработал. Либо, может кто-то подскажет, как реализуется опрос в подобных программах?

Автор: GremlinProg 20.3.2012, 10:13
Цитата(LeonidPr @  20.3.2012,  12:03 Найти цитируемый пост)
может кто-то подскажет, как реализуется опрос в подобных программах?

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

Автор: LeonidPr 20.3.2012, 10:33
Понял, спасибо!

Автор: Dem_max 20.3.2012, 11:07
Есть такое понятие как асинхронная передача(прием) данный, так вот при асинхронной передаче(прием) задается таймаут на операцию записи(чтения). При возникновении таймаута, операция считается законченной.

Автор: xvr 20.3.2012, 13:53
Цитата(LeonidPr @  20.3.2012,  10:03 Найти цитируемый пост)
Как реализовать подобный алгоритм работы в windows?

Отказаться от Windows и от PC  smile 
В ModBUS RTU есть требования к формированию и детектированию интервалов между символами в линии с точностью до 0.5 символьного интервала. Windows этого принципиально делать не умеет, т.к. она не realtime система. Стандартный RS232 порт в PC для этого тоже не подходит, т.к. у него есть FIFO, и интервал между символами, как он их будет отдавать в софт, будет не совпадать с интервалом, как он их принимал. Единственный выход - отключить FIFO.

Возможно сделать некую реализацию ModBUS RTU на PC + Windows выкрутив таймауты в 0 и запустив работу с портом в нитке с reat-time приоритетом, но это увы не будет гарантировать 100% работоспособность - ваш ModBUS может несколько суток/месяцев/лет проработать без нареканий, а потом в самый неподходящий момент потерять пакет другой  smile 

Автор: LeonidPr 20.3.2012, 14:32
Я понимаю, что в точности контроль таймингов, заложенный в спецификации ModBus RTU на PC не сделать, да это и не требуется. GremlinProg дал возможный вариант реализации опроса.
Меня просто интересует тема создания системы сбора данных (в частности по ModBus) и визуализации полученной информации (не полноценная SCADA а только визуализация).
Вот и думаю, как делать опрос устройств, ведь компьютер может быть подключен через преобразователь к шине RS-485 с кучкой устройств, и со всех нужно собрать данные (для программы весь сбор ведется через один экземпляр порта).
Может быть есть какая-нибудь литература по разработке такого рода программ или отдельные статьи?

Автор: Dem_max 20.3.2012, 16:11
ModBUS - это же протокол передачи данных, причем тут физический уровень передачи данных ( RS-485, RS-232б Ethernet) ????? 

Автор: xvr 20.3.2012, 16:39
Цитата(LeonidPr @  20.3.2012,  14:32 Найти цитируемый пост)
GremlinProg дал возможный вариант реализации опроса.

Если по MudBUS'у будут идти пакеты один за другим, то вы их не сможете отделить друг от друга. В ModBUS RTU задержки между байтами входят в структуру передаваемых пакетов.

Цитата(LeonidPr @  20.3.2012,  14:32 Найти цитируемый пост)
Вот и думаю, как делать опрос устройств, ведь компьютер может быть подключен через преобразователь к шине RS-485 с кучкой устройств, и со всех нужно собрать данные (для программы весь сбор ведется через один экземпляр порта).

Работать будет крайне ненадежно.

Цитата(LeonidPr @  20.3.2012,  14:32 Найти цитируемый пост)
Может быть есть какая-нибудь литература по разработке такого рода программ или отдельные статьи?

Одной литературой тут не отделаешся, для этого ставят железки снаружи. И железки более интелектуальные, чем преобразователь RS485 <-> RS232

Цитата(Dem_max @  20.3.2012,  16:11 Найти цитируемый пост)
ModBUS - это же протокол передачи данных, причем тут физический уровень передачи данных

Кривой это протокол, увы. Точнее его ипостась ModBUS RTU over serial line

Автор: LeonidPr 20.3.2012, 19:57
Цитата

Если по MudBUS'у будут идти пакеты один за другим, то вы их не сможете отделить друг от друга.

В общем-то я не спорю, но ModBus же работает по принципу запрос-ответ и пакеты не будут идти чаще, чем я отправляю запросы. Или я ошибаюсь?
Цитата

Работать будет крайне ненадежно.

Почему, объясните, если не сложно?
Цитата

для этого ставят железки снаружи

Знаю, а эти железки наверх уже отдают информацию по TCP/IP.
Цитата

Кривой это протокол, увы. Точнее его ипостась ModBUS RTU over serial line

Опять же, хотелось бы услышать ваше мнение почему? Потому что размер пакета явно не передается?

Автор: xvr 21.3.2012, 10:22
Цитата(LeonidPr @  20.3.2012,  19:57 Найти цитируемый пост)
В общем-то я не спорю, но ModBus же работает по принципу запрос-ответ и пакеты не будут идти чаще, чем я отправляю запросы.

Если ваша программа - мастер, и она не шлет пачки пакетов, то да.
В вашем случае наверное можно сделать нечто 'для опроса устройст по ModBUS' (только не называйте это полноценным ModBUS устройством  smile )

Цитата(LeonidPr @  20.3.2012,  19:57 Найти цитируемый пост)
Почему, объясните, если не сложно?

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

Цитата(LeonidPr @  20.3.2012,  19:57 Найти цитируемый пост)
Знаю, а эти железки наверх уже отдают информацию по TCP/IP.

В принципе достаточно было бы ModBUS ASCII

Цитата(LeonidPr @  20.3.2012,  19:57 Найти цитируемый пост)
 Потому что размер пакета явно не передается? 

Потому что временные характеристики передачи в физическом канале явно учавствуют в формировании протокола передачи. Это невозможно реализовать на любом UART порту. Необходима либо специальная выделенная железка, либо RealTime OS либо поддержка со стороны аппаратуры

Автор: LeonidPr 27.3.2012, 14:54
Подумал тут на досуге и дошло, что вопрос какой-то пустой получился, по крайней мере в применении к ModBus. Как я уже писал, я знаю, какого размера ответ должен прийти, вот прихода стольких байт и надо ждать. А проблема какая-то надуманная получилась. Она наверное на сервере более актуальная, когда действительно не знаешь, какого размера запрос придет.
Спасибо за помощь, тему закрываю.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)