Российский производитель и разработчик сертифицированного измерительного оборудования с 1987 года

Возможно ли что может произойти задержка приема при работе через сеть?

Вы не вошли.

 Поиск | Регистрация | Вход 

23.05.2019 11:56:28
#1

Участник
Здесь с 12.12.2016
Сообщений: 73

Возможно ли что может произойти задержка приема при работе через сеть?

Два крейта подключены к компьютеру по сети в каждом крейте по два LTR27.

Работает мой собственнй OPC сервер, ошибки недочитывая, ошибки обработки данных обрабатываются, все работает.

И вдруг через какое-то время обнаруживается, что отображение канала передающего давления идет с явным запазданием, причем ошибок считывания нет, данные меняются, но они неактуальны. После перезапуска софта (гейта и его клиентов) все начинает работать...
Может ли это быть связано с работой ltrd?

23.05.2019 13:47:22
#2

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,291

Re: Возможно ли что может произойти задержка приема при работе через сеть?

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

В самом ltrd не может быть значительных задержек, служба постоянно принимает данные и немедленно перекладывает их в буфер готовности для чтения клиентами.

Чаще всего подобная проблема (если речь идет о больших задержках в несколько секунд и более и эта задержка не восстанавливается) связана с тем, что в программе прием данных (через Recv) выполняется с меньшей скоростью, чем их принимает ltrd от модуля. В этом случае скорость поступления данных от модуля выше, чем скорость приема данных клиентом и постоянно увеличивается количество несчитанных данных. Т.к. скорость данных у LTR27 небольшая, а разница в скоростях чтения и передачи еще меньше, то увеличение размера непрочитанных данных происходит медленно и может пройти достаточно много времени перед тем как буфер переполнится или хотя бы ltrd зафиксирует в статистике увеличение кол-ва данных в буфере модуля (т.к. есть еще буфер канала передачи данных между ltrd и клиентом, который сперва должен заполниться).
Т.е. это происходит, если Recv(size) вызывается реже чем этот size отсчетов в среднем приходит. Как правило это происходит, когда Recv вызывается не постоянно с ожиданием новых данных внутри Recv, а по какому-нибудь таймеру, у которого есть свои задержки срабатывания и частота которого не синхронизирована с частотой модулей, либо если между Recv() одного модуля в этом же потоке вызываются другие функции, которые могут ожидать каких-то событий длительное время (например прием данных других модулей или ожидание события или другие функции работы с устройствами, которые могут занимать определенное время) и т.п.

24.05.2019 08:54:24
#3

Участник
Здесь с 12.12.2016
Сообщений: 73

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Я думаю я нашел проблему, но пока не решение. Проблема заключаеся в фунцкции считывания данных с модуля.

1. В моем OPC сервере есть класс LTR27. В нем есть функция считывания данных Serv().

2. Каждый экземпляр класса модуля имеет свою нить, но DataThread для всех модулей одна, и как
аргумент в нее передается указатель на класс модуля. И поэтому указателю и вызывается считывание нужного модуля.

3. Функция Serv() класса LTR27 выглядит так:

---------
bool ltr_mod27::Serv()
{
CSLock wait(&CS);

DWORD buf[16];
// забираем данные АЦП
DWORD size= LTR27_Recv(&ltr27, buf, NULL, 16, 1000);
if(size==16) {
  double data[16];
  // применяем калибровку и переводим в вольты
  int res=LTR27_ProcessData(&ltr27, buf, data, &size, 1, 1);
  ....
}
-----------

Так как LTR27 модулей несколько, то У меня есть несколько экземпляров LTR27.
Так как я считаю, что функция LTR27_Recv может обращаться к самому крейту, то вызовы Serv() из разный нитей по идее могут привести к конфликту. Т. е. считывание каждого модуля должно происходить строго по очереди.

Для этого я делаю критическую секцию CSLock wait(&CS), которая тормозит нитки других модулей LTR27 пока один из LTR27 работает с Serv() и соответсвенно с LTR27_Recv().

Частота дискретизации модулей 10 герц.

Как я сейчас понимаю, один модуль, допустим первый, читает данные при помощи LTR27_Recv() и это функция висит 100 мсек пока не примет данные. Вместе с этим висит блокированная функция Serv(). И в это время откачка из других модулей также остановлена! Т.е. если модуля четыре, то последний заберет свои 16 параметров только после паузы 300 мсек.

В связи с этим есть вопросы. Если мы имеем 4 одинаковых модуля, то действительно ли надо делать критическую секцию при считывании LTR27_Recv(&ltr27, buf, NULL, 16, 1000)? Может ничего плохого не произойдет если еще одна нитка LTR27 вызовет функцию Serv()?

Еще вопрос - если буфер модуля недоскачен - можно ли определить сколько данных в нем содержится на данный момент? Если это возможно, то тогда в Serv() можно организовать полное скачивание накопленных данных.

24.05.2019 10:51:30
#4

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,291

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Работа с каждым модулем идет независимо и не влияет на другие модули, поэтому вполне корректно вызывать в параллель Recv для разных модулей из разных потоков без критических секций, в общем это одна из причин для чего нужна сама служба ltrd - обеспечение независимой работы с каждым модулем как с независимым устройством.
Думаю когда сделаете параллельный прием данных без данной секции проблема должна исчезнуть.

Получить количество несчитанных данных к сожалению нельзя. Можно только их вычитать с небольшим таймаутом (но тогда их может быть не кратно 16 и это придется обрабатывать). Но по сути Вам главное, чтобы время между Recv() было меньше времени прихода самого блока.

28.05.2019 12:56:46
#5

Участник
Здесь с 12.12.2016
Сообщений: 73

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Алексей L Card пишет:

Работа с каждым модулем идет независимо и не влияет на другие модули, поэтому вполне корректно вызывать в параллель Recv для разных модулей из разных потоков без критических секций, в общем это одна из причин для чего нужна сама служба ltrd - обеспечение независимой работы с каждым модулем как с независимым устройством.
Думаю когда сделаете параллельный прием данных без данной секции проблема должна исчезнуть.

Много тестировал и в общем могу сказать следущее. Четыре одинаковые LTR27 модуля, работающие на разных нитках, могут вызывать функцию LTR27_Recv без критической секции - но только если все модули находятся в одном крейте. Если же модули разнесены на два крейта, то обращения из разных нитей периодически вызывают коллизии в работе крейтов (с периодом от 3 часов до получаса, но стабильно) . Как правило все начинается с отрубания модулей второго крейта (LTR27_Recv начинает возвращать 0).  Но первый крейт тоже можеть проглючить в одиночку. Бывает, что отрубаются сразу оба крейта. Перезапуск модулей помогает, хотя и занимает по 2-3 секунды на каждый.

Я так думаю, что есть какой-то момент времени когда обращение на чтение из одного модуля приводит к конфликту при чтении из нити другого модуля из другого крейта. Трудно сказать. Есть ли у вас возможность запустить и потестить работу двух крейтов в каждом из которых  по два (ну или более) LTR27? У меня в личном распоряжении только одни крейт и все 4 модуля LTR27 на нем работают в этом случае OK, без критической секции на чтении (которая как я напоминаю вызывает недочитывание буферов модулей).

Что касается идеи вычитывания остатков из буферов, то тут прежде всего надо учитывать, что эти данные фактически придется выкидывать.

28.05.2019 13:52:12
#6

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,291

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Вообще это технически не связанные процессы - чтение данных от разных модулей по разным экземплярам структуры TLTR27, ltrd всегда читает потоки из крейтов и раскидывает их в буферы для клиентов по модулям и каждый Recv забирает данные уже из своего буфера своего канала связи. При этом ltrd - другой процесс, и мне сложно представить как может чтение из разных потоков влиять на его работу.

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

29.05.2019 08:36:20
#7

Участник
Здесь с 12.12.2016
Сообщений: 73

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Уточните пожалуйста:

DWORD size_Recv = LTR27_Recv(&ltr27, buf, NULL, 16, 1000);

Из документации:
-----Beginning of the citation-----
Возвращаемое значение:
Значения меньшие нуля следует интерпретировать как коды ошибок. Значения
большие или равные нулю следует обрабатывать как количество реально
принятых от модуля отсчетов за отведенный интервал времени.
----- The end of the citation -----

Правильно я понимаю, что при заданных мной параметрах LTR27_Recv возвратит либо 16 либо 0 либо ошибку?

29.05.2019 13:40:55
#8

Сотрудник "Л Кард"
Здесь с 17.04.2014
Сообщений: 1,291

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Строго говоря не совсем, если от модуля придет меньше слов на момент истечения таймаута, то функция вернет это значение между 0 и 16. Другой вопрос, что в случае LTR27 все 16 слов передаются одновременно, поэтому как правило это будет верно, но можно представить ситуацию, особенно по сети, что при объединении потоков от модулей крейт и передачи пакетов получится разрыв пакета в середине кадра, второй задержится и если в этот момент истечет таймаут LTR27_Recv(), то при совпадении этих событий  Recv вернет часть кадра и значение меньше 16, так что строго говоря имеет право вернуть любое значение от 0 до 16 (другой вопрос, в зависимости от подхода, если таймаут на примем большой, то это можно интерпретировать как нарушение работы)

30.05.2019 09:44:06
#9

Участник
Здесь с 12.12.2016
Сообщений: 73

Re: Возможно ли что может произойти задержка приема при работе через сеть?

Алексей L Card пишет:

можно представить ситуацию, особенно по сети, что при объединении потоков от модулей крейт и передачи пакетов получится разрыв пакета в середине кадра, второй задержится и если в этот момент истечет таймаут LTR27_Recv(), то при совпадении этих событий  Recv вернет часть кадра и значение меньше 16

Но так как в LTR27 индексы 16 каналов совпадают с буфером, то при принятии меньшего число будет непонятно к каким каналам что относится.  Надо сказать что я никогда не встречал такого в LTR27 и решил игнорировать такие данные (в этом случае не обновлять теги OPC сервера, но в то же время оставить на них хорошое качество).

Что касается ошибок, то я нашел в чем дело. Это пришло с кодом который мне достался по наследству. В нем возврат нуля функцией LTR27_Recv() обрабатывался как сбой, в то время как это не ошибка - ошибки это отрицательные значения. Словом
DWORD size_Recv = LTR27_Recv(&ltr27, buf, NULL, 16, 1000);
это неправильно (DWORD == unsigned int) , должно быть
int size_Recv = LTR27_Recv(&ltr27, buf, NULL, 16, 1000); c обработкой минусов как ошибок.

И действительно, никаких переключений крейтов во время LTR27_Recv нет, данные берутся в ltrd из размеченной по каналам памяти, стало быть критическая секция при работе нескольких одинаковых модулей  не нужна.

Контакты

Адрес: 117105, Москва, Варшавское шоссе, д. 5, корп. 4, стр. 2

Многоканальный телефон:
+7 (495) 785-95-25

Отдел продаж: sale@lcard.ru
Техническая поддержка: support@lcard.ru

Время работы: с 9-00 до 19-00 мск