Содержание |
Сокращения
|
С точки зрения пользователя, DIM - это библиотека функций на языках C, C++, Fortran, Pascal, позволяющих достаточно просто организовать обмен данными в распределенных измерительных системах. Технология TCP/IP (например, в виде сокетов) оперирует понятиями типа "канал связи", "соединение" и пользователь должен сам заботиться об установлении сеанса связи, приеме и передаче данных и т.д. Технология DIM вместо этого оперирует понятиями "сервис", "набор данных", скрывая от пользователя детали установления связи, низкоуровневые протоколы обмена данными и т.д. Хотя внутри DIM, конечно, используются те же самые сокеты.
Понятие "сервис" есть абстракция более высокого уровня, чем "канал связи". "Сервис" есть поименованный набор данных фиксированной, но не оговоренной заранее структуры данных. Структура данных известна серверу и клиенту, но неизвестна библиотеке DIM. DIM берется передавать в асинхронном режиме данные сервиса между клиентом и сервером. Обновление происходит автоматически, по таймеру или по вызову функции обновления сервиса. Никаких забот об установлении соединения, протоколе связи нет.
Большим плюсом и достоинством DIM являются:
DIM - сервер для CRW-DAQ - это набор средств, адаптирующий технологию DIM для системы CRW-DAQ. Это абстракция следующего уровня, надстройка над DIM. С точки зрения пользователя, это уже не набор функций, а набор правил конфигурирования сервера, позволяющий обеспечить работу распределенной системы из нескольких машин, на которых может быть запущено несколько экземпляров CRW-DAQ и других программ, поддерживающих DIM. Конфигурирование сервера основано не на функциях, а на тегах. С точки зрения пользователя, он должен описать поименованные наборы тегов, а также правил, по которым эти наборы будут автоматически обновляться сервером DIM.
DNS - это сервер имен DIM. Для чего он нужен? Надо сказать, что DIM построен по классической технологии клиент-сервер. Сервер предоставляет клиенту информационные ресурсы, клиент их потребляет. Клиент может воздействовать на сервер путем посылки команд.
Сервер может обслуживать много клиентов, то есть предоставлять нескольким клиентам одну и ту же информацию. Поэтому отношение передачи данных "сервер -> клиент" есть отношение типа "один ко многим".
Сервер может обслуживать также команды (запросы) многих клиентов одновременно, выстраивая запросы в очередь и выполняя их один за другим. Поэтому отношение передачи данных "клиент -> сервер" есть отношение типа "многие к одному".
В чем недостаток классической клиент-серверной технологии? В принципе, каждое соединение клиент-сервер есть соединение "point to point", требующее описания клиента и сервера, включая сюда имя компьютера клиента и сервера, идентификатор сеанса связи и т.д. По установленному каналу связи данные передаются по известному клиенту и серверу протоколу. При таком подходе сервер должен знать имена каждого клиента, чтобы делать рассылку данных, а каждый из клиентов должен знать имя сервера. В системах со сложной топологией дело осложняется тем, что каждый компьютер одновременно может выступать как клиент и как сервер - для разных наборов данных. К этому надо добавить, что имена и адреса компьютеров не есть постоянная величина. А на этапе проектирования эти имена вообще неизвестны. Таким образом, конфигурирование классической клиент-серверной системы представляется громоздким и неудобным.
DIM предлагает другую концепцию. Основным понятием DIM является не "канал связи", а "сервис". Сервис есть просто поименованный набор данных. Сервер берется предоставлять этот поименованный набор данных клиентам. Технология DIM обеспечивает передачу данных клиентам, привязанную к именам наборов данных, а подробности передачи данных скрываются. В конце концов, клиенту именно это и надо - получать от сервера данные. Сеанс связи - это для клиента лишние детали, а не результат.
Однако, поскольку имена компьютеров знать все же надо, DIM использует сервер имен DNS. Сервер имен - это программа, запускаемая на одном из компьютеров сети, которая хранит информацию о клиентах и серверах. Когда сервер начинает работу, он соединяется с DNS-сервером имен и передает ему список сервисов, которые он публикует, то есть может предоставить клиентам. Когда клиент начинает работу, он обращается к DNS-серверу с просьбой дать адрес сервера, который обслуживает интересующий клиента сервис. Получив адрес сервера, клиент устанавливает соединение. После установления соединения DNS-сервер, в принципе, уже не нужен, по крайней мере для данной пары клиент-сервер. Однако, поскольку связь может рваться, а клиенты - отсоединяться и вновь присоединяться, DNS-сервер работает как постоянная служба. Что-то вроде службы знакомств.
Таким образом, вместо пары (имя клиента, имя сервера) технология DIM использует пару (имя DNS-сервера, имя сервиса). Достоинство в том, что имя DNS-сервера одно для всех компьютеров в рамках данной сети, а имя сервиса есть константа, определяемая проектировщиком измерительной системы произвольно. При смене имен компьютеров ничего не меняется, проектировщик измерительной системы ничего не должен знать о компьютерах сети, кроме того, как называется DNS-сервер.
Как следствие, сервер и клиент благодаря DIM могут ничего не знать друг о друге (с точки зрения пользователя). Сервер просто публикует данные своих сервисов, не заботясь, какие клиенты их берут и сколько их подключено. Клиент просто берет данные по имени сервиса, не заботясь о том, какой сервер их предоставил. Сплошная идиллия.
Надо заметить, что DNS-сервер следит также за порядком в своей сети. Если какой-то сервер зарегистрировал сервис и запускается другой сервер, который тоже хочет опубликовать сервис с таким же именем, то этому запускаемому серверу будет мягко предложено покончить жизнь самоубийством, поскольку место под солнцем уже занято. Поэтому проектировщик измерительной системы должен позаботиться об уникальности имен сервисов.
Наконец, для обзора текущего содержимого DNS-сервера служит утилита DID. Эта утилита незаменима при отладке DIM приложений, позволяя узнавать, какие серверы есть в сети, какие сервисы они публикуют, какие клиенты к ним подключены и т.д.
Наконец, надо сказать, что если выбрать в качестве сервера имен одну из машин, где будет запускаться DIM-сервер для CRW-DAQ, то служба DNS (файл dns.exe) будет запущена автоматически. Если это не так, надо позаботиться о запуске DNS, иначе соединение между клиентами и серверами не будет установлено.
С точки зрения пользователя системы CRW-DAQ, программы DIMSRV.PAS,DIMSRV.EXE являются готовым инструментом, модифицировать их не надо. Все, что надо пользователю - грамотно составить конфигурацию сервера, то есть описать, какие данные и каким образом надо автоматически пересылать.
С точки зрения исполнения и управления, основной (ведущей) является встроенная программа DIMSRV.PAS. Она запускается в составе системы CRW-DAQ и отвечает за конфигурирование, запуск и останов автономной программы DIMSRV.EXE. При сбое автономной программы сервера, она будет автоматически перезапущена. Автономная программа общается с встроенной программой по анонимному каналу. Впрочем, для пользователя это лишние подробности.
Файлы сервера помещаются в каталог ~~\Resource\DaqSite\DimServer, где ссылка ~~ заменяет каталог, где находится основной исполняемый файл системы CRW-DAQ. Для работы сервера нужны (не считая файлов конфигурации) такие файлы:
Сначала надо объявить программу - сервер DIM для CRW-DAQ. Это делается путем включения ссылки на стандартную конфигурацию:
[ConfigFileList] ; Включаем в конфигурационный файл ConfigFile = ~~\resource\daqsite\default\dimsrv.cfg ; Ссылка на стандартную конфигурацию &DimSrv [] [&DimSrv] ; Параметры конфигурации сервера &DimSrv: DIM_TASK = DEMO/SERVER ; Имя сервера, уникальное в пределах DIM-сети DIM_DNS_NODE = . ; Имя DIM DNS сервера, для localhost - точка []Стандартная конфигурация &DimSrv включает пути поиска [DAQ] SearchPath = … , которые нужны для поиска необходимых для сервера программ. Кроме того, стандартная конфигурация содержит набор параметров, подходящих для подавляющего большинства задач, кроме DIM_TASK и DIM_DNS_NODE, которые задаются индивидуально для каждой системы.
&DIMSRV : Stat.Info dis_info dis_cmnd dic_info dic_cmnd
&DIMSRV MsgPerSec 0.00 0.00 0.00 99.90
&DIMSRV TagPerSec 0.00 0.00 0.00 4995.00
&DIMSRV ChrPerSec 0.00 0.00 0.00 39260.74
[&DimSrv]
AnalogOutputs = 12
Link AnalogOutput 0 with curve MsgPerSec.dis_info history 100
Link AnalogOutput 1 with curve MsgPerSec.dis_cmnd history 100
Link AnalogOutput 2 with curve MsgPerSec.dic_info history 100
Link AnalogOutput 3 with curve MsgPerSec.dic_cmnd history 100
Link AnalogOutput 4 with curve TagPerSec.dis_info history 100
Link AnalogOutput 5 with curve TagPerSec.dis_cmnd history 100
Link AnalogOutput 6 with curve TagPerSec.dic_info history 100
Link AnalogOutput 7 with curve TagPerSec.dic_cmnd history 100
Link AnalogOutput 8 with curve ChrPerSec.dis_info history 100
Link AnalogOutput 9 with curve ChrPerSec.dis_cmnd history 100
Link AnalogOutput 10 with curve ChrPerSec.dic_info history 100
Link AnalogOutput 11 with curve ChrPerSec.dic_cmnd history 100
Смысл каждого из выходов вполне понятен по названию кривой в данном примере.
Следующее, что надо сделать - объявить сервисы, которые будет обслуживать сервер. Это делается примерно так:
[&DimSrv.ServiceList] dis_info_nick = dis_info TEST1/INFO_SERVICE dis_cmnd_nick = dis_cmnd TEST1/CMD_SERVICE dic_info_nick = dic_info TEST2/INFO_SERVICE dic_cmnd_nick = dic_cmnd TEST2/CMD_SERVICEЗдесь:
devPostMsg('&DimSrv ##dis_info_nick'); приведет к обновлению сервиса
TEST1/INFO_SERVICE (то есть клиенты получат свежие данные).
Следующее, что надо сделать - описать объявленные сервисы, которые будет обслуживать сервер. Это делается примерно так:
[dis_info_nick] tag dis_info_i tag dis_info_r tag dis_info_s polling MONITORED,0 filling /////w== //// &DimCtrl [dis_cmnd_nick] tag dis_cmnd_i, dis_cmnd_r, dis_cmnd_s devPostMsg &DimCtrl #dis_cmnd_receive [dic_info_nick] tag dic_info_i tag dic_info_r tag dic_info_s devPostMsg &DimCtrl #dic_info_receive polling MONITORED,0 filling /////w== //// &DimCtrl [dic_cmnd_nick] tag dic_cmnd_i, dic_cmnd_r, dic_cmnd_s polling TIMED,1000Здесь:
devPostMsg('&DimSrv ##'+str(tag)) или
devPostMsg('&DimSrv ##dis_info_nick')
В первом случае передается тег (не значение, а ссылка!), любой из данного сервиса.
Во втором случае передается кличка (не сетевое имя!) данного сервиса.
Этот метод применяется в случае polling MONITORED,0когда обновления по таймеру нет. При указании обновления по таймеру данные из тегов обновляются автоматически с заданным периодом.
devPostMsg &DimCtrl #dic_info_receiveприведет к вызову
devPostMsg("&DimCtrl #dic_info_receive") при каждом обновлении данного сервиса.
Заметим, что поле polling не обязательно, по умолчанию принят по метод MONITORED,0,0.
В сообщениях можно использовать также следующие выражения:
devPostMsg &Client dic_info_data=%** devSendMsg &Client dic_info_tags=%01,%02,%03Использование этих подстановок позволяет организовать самостоятельную обработку сообщений клиентами. Это позволяет также обрабатывать команды без потерь, то есть выполнять сериализацию потока сообщений.
Сериализация - это выстраивание одновременных событий в очередь FIFO с последующей асинхронной выборкой из очереди и обработкой. Без сериализации сообщения могут быть потеряны. Дело в том, что если сообщение (сервис) было принято по сети несколько раз за данный квант времени, первые значения тегов будет затерты последующими, так как теги истории не имеют. При необходимости сериализации (обработки всех поступающих сообщений без потерь, по порядку) можно пересылать данные клиенту, пусть сам разбирается. При этом сообщения теряться не будут.
Сериализация нужна не всегда. Например, сериализация не нужна при редких событиях, четко разнесенных по времени или для отображения медленно меняющихся величин. При обработке команд от клиентов сериализация может понадобиться, так как клиенты могут одновременно вызывать различные команды, а сервер должен их все выполнять. Именно в этих случаях имеет смысл переложить обработку на другие программы, пересылая им "сырые" данные.
Сериализация при посылке сообщений (для постановки команд в очередь), если нужна, делается либо посылкой сообщения с установкой данных, либо так:
data:=dump(i);
Эта команда используется для посылки сериализованных сообщений.
То есть сообщения будут выстраиваться в очередь и не будут пропадать,
даже если несколько сообщений было послано одновременно.
var i:integer; r:real; s:string;
data:=dump(i)+dump(r)+s+chr(0);
Обратите внимание, что строковые данные должны идти с завершающим нулем chr(0).
Эта команда используется для посылки сериализованных сообщений.
То есть сообщения будут выстраиваться в очередь и не будут пропадать,
даже если несколько сообщений было послано одновременно.
@dns.exe Запуск dns.exe, если он еще не запущен
Возвращает число работающих процессов dns.exe
@dns.exe Period Печатает период проверки(мс) процесса dns.exe
Нулевой период означает отключение проверок
@dns.exe Period 60000 Установка периодичности проверки (мс) dns.exe
При проверке, если dns.exe (еще) не запущен, он запускается
Задание периода проверки @dns.exe Period 60000 означает, что раз в минуту
будет выполяться команда dns.exe, которая будет проверять наличие процесса
dns.exe и запускать его, если он "упал".
Это гарантирует постоянную работу сервера имен dns.exe.
@ReportFlags 0 отключить вывод сообщений об ошибках
@ReportFlags 1 включить вывод сообщений об ошибках в консоль устройства
@ReportFlags 2 включить вывод сообщений об ошибках в Главную Консоль
@ReportFlags 3 включить вывод сообщений об ошибках в обе консоли
@DimBridge Period 60000 ; задать период проверки/перезапуска в 1 минуту
@DimBridge egp-mzbs.dep0404.ru egp-main.dep0404.ru EGP/* ; экспорт сервисов EGP/* из egp-mzbs в egp-main
@DimBridge . simply.dep0404.ru DOZA/* ; экспорт сервисов DOZA/* из localhost в simply
@DimBridge localhost simply.dep0404.ru DOZA/* ; экспорт сервисов DOZA/* из localhost в simply
@DimBridge %HostName% simply.dep0404.ru DOZA/* ; экспорт сервисов DOZA/* из localhost в simply
@DimBridge %ComputerName% simply.dep0404.ru DOZA/* ; экспорт сервисов DOZA/* из localhost в simply
@DimBridge start ; запуск всех объявленных процессов DimBridge
@DimBridge kill ; остановка всех работающих процессов DimBridge
@DimBridge stop ; остановка всех работающих процессов DimBridge
@DimBridge restart ; перезапуск всех работающих процессов DimBridge
@DimBridge init ; (ре)инициализация - вернуть начальное состояние
@DimBridge view ; просмотр списка процессов DimBridge
Обратите внимание, что в качестве имени текущего локального компьютера в команде @DimBridge
допустимо использовать . или %ComputerName% (краткое имя) или %HostName% (полное имя).
см. также DimBridge.
@DimPorts add enable ; разрешить TCP порты для DIM в Firewall
@DimPorts delete ; удалить разрешения портов DIM
@DimPorts show ; показать список правил Firewall
DimBridge.exe dns1.net dns2.net DNS1/DATA/*Есть веская причина использовать мосты в измерительных системах. Допустим, есть несколько серверов (например host1, host2, host3, ...), которые обслуживают автономные подсистемы и могут работать независимо друг от друга, а также центральный сервер (например, simply). Если DNS-сервер по какой-то причине будет недоступен, то клиент/серверные процессы не смогут связаться друг с другом, даже если они расположены на одном компьютере. При этом использование DIM для связи процессов, работающих на одной машине, является распространенной практикой. Часто даже один процесс выступает клиентом по отношению к самому себе - например, при разработке распределенного графического интерфейса.
На сервере host1:
DimBridge.exe host1.net simply.net HOST1/DATA/* ; экспорт данных с серверного на центральный компьютер
На клиенте host2:
DimBridge.exe simply.net host2.net HOST1/DATA/* ; экспорт данных с центрального на клиентский компьютер
При этом мостов может быть несколько, в зависимости от числа серверов, участвующих во взаимодействии.
Эти мосты надо как-то запускать, а также отслеживать их состояние, чтобы перезапускать "упавшие" мосты.
@StatPeriod 60000 ; задать период печати статистики, ms (0-отключить) @DimBridge Period 60000 ; период проверки/перезапуска мостов, ms (0-отключить) @DimBridge host1.net host2.net DATA/* ; добавление моста данных DATA/* из host1 в host2 @DimBridge View ; просмотр списка мостов @DimBridge Init ; удалить все мосты, привести в начальное состояние @DimBridge Stop ; остановить все работающие процессы мостов @DimBridge Start ; запустить все процессы мостов @DimBridge Restart ; перезапустить все процессы мостов @IfHostName n c ; выполнить команду c, если полное имя компьютера (FQHN) равно n @IfNotHostName n c ; выполнить команду c, если полное имя компьютера (FQHN) не равно n @IfComputerName n c ; выполнить команду c, если краткое имя компьютера равно n @IfNotComputerName n c ; выполнить команду c, если краткое имя компьютера не равно nПриведенные команды (@DimBridge) позволяют запускать до 32 мостов и следить за их состоянием (с периодом @DimBridge Period). Если процесс моста (DimBridge.exe) "упал", то он перезапускается. Эти команды вызываются, например, в секции [&DimSrv.StartupScript]:
[&DimSrv.StartupScript] @StatPeriod 60000 @DimBridge Period 60000 @IfComputerName egp-mzbs @DimBridge egp-mzbs.dep0404.ru simply.dep0404.ru EGP/MZBS/* @IfComputerName egp-main @DimBridge simply.dep0404.ru egp-main.dep0404.ru EGP/MZBS/* [] Обратите внимание - на разных компьютерах будут запускаться разные мосты. В данном примере на сервере egp-mzbs данные копируются из egp-mzbs на simply, а на клиенте egp-main данные копируются из simply на egp-main.Таким образом, в одной конфигурации можно описать клиент-серверную систему с локальными DNS (для надежной локальной связи) и центральным DNS (для объединения в систему).
Из консоли CMD:
DimPorts add enable - разрешить DIM-порты TCP 2505,5100..5108
DimPorts delete - удалить разрешения для DIM-портов
DimPorts show - показать разрешения Firewall
Из консоли &DimSrv:
@DimPorts add enable - разрешить DIM-порты TCP 2505,5100..5108
@DimPorts delete - удалить разрешения для DIM-портов
@DimPorts show - показать разрешения Firewall
Команда также доступна в меню Инструменты\Консольные утилиты.