Принцип работы коннекторов в Delphi компонентах
В моих компонентах для Delphi коннектор – это объект, осуществляющий связь с внешними объектами(объектом). Внешним объектом может выступать другая программа или другое устройство, которое поддерживает тот же интерфейс или протокол связи. В процессе связи коннектор выступает клиентом. То есть задача коннектора отправить запрос и при необходимости дождаться ответа и отправить его по обратной связи (CallBack).
TKRConnector – это базовый класс всех коннекторов. Ниже представлена схема работы коннектора

Для отправки запроса используется метод Send
Задача данного метода отправить информацию о запросе в очередь на обработку. В методе Send передаются следующие параметры:
- APack – указатель на буфер в котором находятся данные предназначенные для отправки. Если нужно получить ответ, то он сохранится в этот же буфер.
- ALength – длинна отправляемых данных в байтах.
- ACallBack – метод обратной связи типа TKRConnectorCallBack. Данный метод будет вызван после обработки запроса. Если нет необходимости в обратной связи, то можно передать nil.
- AData – указатель на дополнительные данные, который будет передан в метод обратной связи (CallBack). Если есть необходимость передать дополнительную информацию о пакете, которые понадобятся в методе обратной связи, то указатель на эти данные передается в этом параметре. Если нет необходимости что-либо передавать, то устанавливаем nil.
- AWaitResult – указывает на то, нужно ли ждать ответ на запрос. Если должен прийти ответ, но он не будет получен, то это будет считаться ошибкой ceNoResponse.
- ARecvLen – если заранее известна длина ответа, то ее нужно указать в этом параметре. Заранее зная длину ответа коннектор будет быстрее обрабатывать входящие данные.
- ADelimiter – разделитель или последовательность байт разделяющая входящие пакеты. Например в протоколе Modbus ASCII разделителем является последовательность #13#10 и для передачи этой последовательности нужно установить значение $0D0A в данный параметр. Если разделитель не используется, то устанавливаем ноль.
- ADelimiterLen – длина разделителя в байтах. Если разделитель не используется, то устанавливаем ноль.
После вызова Send, информация о запросе попадает во входящую очередь коннектора, которая из себя представляет сблокированный упорядоченный список типа TKRThreadQueue. Максимальное количество запросов в очереди установлено в константе CE_QUEUE_MAX_ITEMS, а текущее количество можно узнать из свойства коннектора QueueCount. Если в момент вызова метода Send в очереди будет максимально возможное количество запросов, то будет вызван метод обратной связи с ошибкой ceQueueOverflowed.
Из входящей очереди запрос попадает в поток обработки данных типа TKRThread. Свойства коннектора WaitTime и WaitPauseTime являются настройками данного потока. Функционал потока описывается для каждого коннектора отдельно, но основные задачи во всех случаях одинаковы:
- Установить соединение. Если связь не установлена, то коннектор пытается подключиться с таймаутом указанным в свойстве ConnectTimeout. Если связи нет, то коннектор будет постоянно пытаться подключиться с периодом между попытками указанным в свойстве ReconnectTime. Все запросы до установки связи будут возвращать ошибку ceNotConnection.
- Отправить запрос. Отправка последовательности бай с таймаутом указанным в свойстве WriteTimeout. Если за указанный период данные отправить не удается, то возвращается ошибка ceDataNotSended.
- При необходимости дождаться ответа. Если при вызове метода Send в параметре AWaitResult передано True, то будет ожидаться ответ в течении времени указанного в свойстве WaitRespTime. Общий таймаут ожидания ответа устанавливается в свойстве ReadTimeout, но промежутки по времени между частями входящего пакета не должны превышать значение свойства WaitRespTime. То есть , фактически, если в течении времени WaitRespTime ничего не будет получено, то коннектор будет считать, что ответа нет. Если в методе Send передано значение ARecvLen больше нуля, то коннектор считает, что ответ получен, если длина полученных данных больше или ровна ARecvLen и прекращает ожидание дополнительных данных. Если ответ получить не удалось, то возвращается ошибка ceNoResponse.
- Результат отправить в исходящую очередь.
Исходящая очередь из себя представляет сблокированный упорядоченный список типа TKRThreadQueue. Максимальное количество запросов в очереди установлено в константе CE_QUEUE_MAX_ITEMS, а текущее количество можно узнать из свойства коннектора QueueOutCount.
Второй поток коннектора предназначен для отправки результата, то есть для вызова метода обратной связи. Свойства коннектора WaitOutTime и WaitPauseOutTime являются настройками данного потока.
Метод обратной связи представляет из себя процедуру какого либо объекта со следующими параметрами:
- AError – ошибка типа TKRConnectorError, возникшая при обработке запроса. Если в параметре придёт ноль ceOK, то значит, что в процессе обработки запроса ошибок не возникло. Текстовые представления ошибок находятся в константе CONNECTOR_ERRORS_MSG. Также текстовое представление ошибки можно получить при помощи метода коннектора ErrorMsg.
- APack – указатель на тот же буфер который был передан в методе Send. В этот буфер записывается ответ, поверх запроса.
- ALength – длина ответа.
- AData – указатель на дополнительные данные который был передан в методе коннектора Send.
В методе обратной связи нужно учитывать то, что он напрямую вызывается из исходящего потока коннектора, то есть асинхронно основному потоку.
На данный момент есть три коннектора основанные на TKRConnector:
- KRBTConnector – беспроводная связь Bluetooth
- KRCOMPortConnector – связь через последовательный порт
- KRTCPConnector – сетевая связь по стеку протоколов TCP/IP
Пример использования
В приведенном ниже примере через коннектор последовательного порта опрашиваются три переменные удаленного устройства по протоколу Modbus RTU. Первая переменная будет типа Word в регистре 0, вторая типа SmallInt в регистре 1 и третья типа DWORD в регистрах 2 и 3. При корректном ответе устройства значения записываются в поля TEdit, а при ошибке в эти же поля записывается текстовое представление этих ошибок. Для синхронизации метода обратной связи с основным потоком используем оконные сообщения Windows.
![]() | Пример использование коннектора на основе класса TKRConnector |
CallBack - это обратная связь с коннекторам. Мы не можем получить ответ от коннектора сразу, так как нужно дождаться ответа от удаленного устройства. По этому, для получения ответа от коннектора мы ему передаем указатель на нашу функцию CallBack:
После того как коннектор получит ответ от удаленного устройства или при ошибке он вызывает функцию CallBack. То есть коннектор вызывает функцию CallBack и вкладывает в нее параметры:
AError - это код ошибки или ноль, если ошибки нет
APack - указатель на буфер который был передан коннектору. Ответ коннектор вкладывает в тот же буфер в котором вы ему передали запрос. Если буфер был зарезервирован в памяти с помощью процедур New или GetMem, то в CallBack нужно очистить память процедурой Dispose или FreeMem
ALength - длина ответного пакета, который находится в буфере
AData - указатель на дополнительные данные, если нужно. Мы его передаем коннектору просто для того, чтобы он его вернул в CallBack
Нужно всегда учитывать тот факт, что CallBack коннектор вызывает из потока. По-этому нужно позаботится о синхронизации с основным потоком.