1
0
mirror of https://github.com/Bayselonarrend/OpenIntegrations.git synced 2025-08-10 22:41:43 +02:00

Доработки по TCP-серверу

This commit is contained in:
Anton Titovets
2025-01-22 23:00:41 +03:00
parent 59d2f806a0
commit d66118b565
10 changed files with 144 additions and 110 deletions

View File

@@ -98,6 +98,7 @@ dependencies = [
"dashmap", "dashmap",
"once_cell", "once_cell",
"serde_json", "serde_json",
"widestring",
] ]
[[package]] [[package]]
@@ -213,6 +214,12 @@ version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14706d2a800ee8ff38c1d3edb873cd616971ea59eb7c0d046bb44ef59b06a1ae" checksum = "14706d2a800ee8ff38c1d3edb873cd616971ea59eb7c0d046bb44ef59b06a1ae"
[[package]]
name = "widestring"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311"
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"

View File

@@ -17,3 +17,4 @@ addin1c = "0.5.0"
serde_json = "1.0.137" serde_json = "1.0.137"
dashmap = "6.1.0" dashmap = "6.1.0"
once_cell = "1.20.2" once_cell = "1.20.2"
widestring = "1.1.0"

View File

@@ -28,14 +28,14 @@ pub fn cal_func(_obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
match num { match num {
1 => { 0 => {
let connection_id = params[0].get_string().unwrap_or("".to_string()); let connection_id = params[0].get_string().unwrap_or("".to_string());
let max_size = params[1].get_i32().unwrap_or(0); let max_size = params[1].get_i32().unwrap_or(0);
commons::receive_data(connection_id, max_size as usize) commons::receive_data(connection_id, max_size as usize)
}, },
2 => { 1 => {
let connection_id = params[0].get_string().unwrap_or("".to_string()); let connection_id = params[0].get_string().unwrap_or("".to_string());
let data = params[1].get_blob().unwrap_or(&[]).to_vec(); let data = params[1].get_blob().unwrap_or(&[]).to_vec();
@@ -43,7 +43,7 @@ pub fn cal_func(_obj: &mut AddIn, num: usize, params: &mut [Variant]) -> Box<dyn
Box::new(commons::send_data(connection_id, data)) Box::new(commons::send_data(connection_id, data))
}, },
3 => { 2 => {
let connection_id = params[0].get_string().unwrap_or("".to_string()); let connection_id = params[0].get_string().unwrap_or("".to_string());
Box::new(commons::close_connection(connection_id)) Box::new(commons::close_connection(connection_id))
} }

View File

@@ -7,6 +7,8 @@ use std::{
ffi::{c_int, c_long, c_void}, ffi::{c_int, c_long, c_void},
sync::atomic::{AtomicI32, Ordering}, sync::atomic::{AtomicI32, Ordering},
}; };
use widestring::U16CStr;
use addin1c::{create_component, destroy_component, name, AttachType}; use addin1c::{create_component, destroy_component, name, AttachType};
@@ -16,17 +18,22 @@ pub static mut PLATFORM_CAPABILITIES: AtomicI32 = AtomicI32::new(-1);
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn GetClassObject(name: *const u16, component: *mut *mut c_void) -> c_long { pub unsafe extern "C" fn GetClassObject(name: *const u16, component: *mut *mut c_void) -> c_long {
match *name as u8 { let u16_name = U16CStr::from_ptr_str(name);
b'1' => { let rust_name = u16_name.to_string().expect("Invalid UTF-16 string");
match rust_name.as_str() {
"Server" => {
let addin = server::AddIn::new(); let addin = server::AddIn::new();
create_component(component, addin) create_component(component, addin)
} },
b'2' => { "Handler" => {
let addin = handler::AddIn::new(); let addin = handler::AddIn::new();
create_component(component, addin) create_component(component, addin)
} },
_ => 0, _ => 0,
} }
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]

Binary file not shown.

Binary file not shown.

View File

@@ -293,31 +293,6 @@
КонецФункции КонецФункции
// Ожидать подключение !NOCLI
// Блокирует выполнение программы до появления нового подключения
//
// Параметры:
// TCPСервер - Произвольный - TCP сервер. См. СоздатьСервер - srv
// Таймаут - Число - Максимальное время ожидания подключений. 0 > бесконечно - timeout
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура с идентификатором нового подключения или ошибкой
Функция ОжидатьПодключение(Знач TCPСервер, Знач Таймаут = 0) Экспорт
Если Не ЭтоСервер(TCPСервер) Тогда
ВызватьИсключение "Переданное значение не является TCP-сервером!";
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут);
Результат = TCPСервер.Wait(Таймаут);
ОбработатьРезультат(Результат);
Возврат Результат;
КонецФункции
// Отключить сервер !NOCLI // Отключить сервер !NOCLI
// Останавливает запущенный сервер // Останавливает запущенный сервер
// //
@@ -341,6 +316,31 @@
КонецФункции КонецФункции
// Ожидать входящие соединения !NOCLI
// Блокирует выполнение программы до появления нового подключения
//
// Параметры:
// TCPСервер - Произвольный - TCP сервер. См. СоздатьСервер - srv
// Таймаут - Число - Максимальное время ожидания подключений. 0 > бесконечно - timeout
//
// Возвращаемое значение:
// Структура Из КлючИЗначение - Структура с идентификатором нового подключения или ошибкой
Функция ОжидатьВходящиеСоединения(Знач TCPСервер, Знач Таймаут = 0) Экспорт
Если Не ЭтоСервер(TCPСервер) Тогда
ВызватьИсключение "Переданное значение не является TCP-сервером!";
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьЧисло(Таймаут);
Результат = TCPСервер.Wait(Таймаут);
ОбработатьРезультат(Результат);
Возврат Результат;
КонецФункции
// Получить входящие соединения !NOCLI // Получить входящие соединения !NOCLI
// Получает список соединений в пуле // Получает список соединений в пуле
// //
@@ -368,7 +368,7 @@
КонецФункции КонецФункции
// Актуализировать входящие соединения // Актуализировать входящие соединения !NOCLI
// Удаляет неактивные соединения из пула // Удаляет неактивные соединения из пула
// //
// Параметры: // Параметры:
@@ -391,28 +391,43 @@
КонецФункции КонецФункции
// Получить данные !NOCLI // Это сервер !NOCLI
// Определяет, является ли переданное значение объектом TCP сервера
//
// Параметры:
// Значение - Произвольный - произвольное значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это сервер
Функция ЭтоСервер(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Server";
КонецФункции
#КонецОбласти
#Область МетодыОбработкиСоединений
// Получить запрос !NOCLI
// Получает данные из потока существующего соединения // Получает данные из потока существующего соединения
// //
// Параметры: // Параметры:
// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd
// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn // IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn
// МаксимальныйРазмер - Число - Максимальный размер данных. 0 > до конца потока - maxsize // МаксимальныйРазмер - Число - Максимальный размер данных. 0 > до конца потока - maxsize
// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd
// //
// Возвращаемое значение: // Возвращаемое значение:
// Структура Из КлючИЗначение, ДвоичныеДанные - Двоичные данные при успехе или структура с описанием ошибки // Структура Из КлючИЗначение, ДвоичныеДанные - Двоичные данные при успехе или структура с описанием ошибки
Функция ПолучитьДанные(Знач TCPОбработчик, Знач IDПодключения, Знач МаксимальныйРазмер = 0) Экспорт Функция ПолучитьЗапрос(Знач IDПодключения, Знач МаксимальныйРазмер = 0, Знач TCPОбработчик = "") Экспорт
Если Не ЭтоСервер(TCPОбработчик) Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик);
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения);
OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер); OPI_ПреобразованиеТипов.ПолучитьЧисло(МаксимальныйРазмер);
Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
Данные = TCPОбработчик.Receive(IDПодключения, МаксимальныйРазмер); Данные = TCPОбработчик.Receive(IDПодключения, МаксимальныйРазмер);
Если ТипЗнч(Данные) = Тип("Строка") Тогда Если ТипЗнч(Данные) = Тип("Строка") Тогда
@@ -431,28 +446,25 @@
КонецФункции КонецФункции
// Отправить данные !NOCLI // Отправить ответ !NOCLI
// Отправляет данные клиенту по идентификатору подключения // Отправляет данные клиенту по идентификатору подключения
// //
// Параметры: // Параметры:
// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd
// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn // IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn
// Данные - ДвоичныеДанные - Данные для отправки - data // Данные - ДвоичныеДанные - Данные для отправки - data
// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd
// //
// Возвращаемое значение: // Возвращаемое значение:
// Структура Из КлючИЗначение - Информация о выполнении // Структура Из КлючИЗначение - Информация о выполнении
Функция ОтправитьДанные(Знач TCPОбработчик, Знач IDПодключения, Знач Данные) Экспорт Функция ОтправитьОтвет(Знач IDПодключения, Знач Данные, Знач TCPОбработчик = "") Экспорт
Если Не ЭтоСервер(TCPОбработчик) Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик);
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения);
OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные); OPI_ПреобразованиеТипов.ПолучитьДвоичныеДанные(Данные);
Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
Результат = TCPОбработчик.Send(IDПодключения, Данные); Результат = TCPОбработчик.Send(IDПодключения, Данные);
ОбработатьРезультат(Результат); ОбработатьРезультат(Результат);
@@ -466,22 +478,19 @@
// Закрывает существующее соединение по идентификатору // Закрывает существующее соединение по идентификатору
// //
// Параметры: // Параметры:
// TCPОбработчик - Произвольный - TCP сервер или идентификатор подключения - hnd
// IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn // IDПодключения - Строка, Число - ID активного подключения. См. ОжидатьПодключение - conn
// TCPОбработчик - Произвольный - TCP сервер или пустое значение при обособленной обоработке - hnd
// //
// Возвращаемое значение: // Возвращаемое значение:
// Структура Из КлючИЗначение - Информация о выполнении // Структура Из КлючИЗначение - Информация о выполнении
Функция ЗакрытьВходящееСоединение(Знач TCPОбработчик, Знач IDПодключения) Экспорт Функция ЗакрытьВходящееСоединение(Знач IDПодключения, Знач TCPОбработчик = "") Экспорт
Если Не ЭтоСервер(TCPОбработчик) Тогда
OPI_ПреобразованиеТипов.ПолучитьСтроку(TCPОбработчик);
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения); OPI_ПреобразованиеТипов.ПолучитьСтроку(IDПодключения);
Если Не ЭтоСерверИлиОбработчик(TCPОбработчик) Тогда
TCPОбработчик = ПодключитьКомпонентуНаСервере("OPI_TCPServer", "Handler");
КонецЕсли;
Результат = TCPОбработчик.Close(IDПодключения); Результат = TCPОбработчик.Close(IDПодключения);
ОбработатьРезультат(Результат); ОбработатьРезультат(Результат);
@@ -491,21 +500,6 @@
КонецФункции КонецФункции
// Это сервер !NOCLI
// Определяет, является ли переданное значение объектом TCP сервера
//
// Параметры:
// Значение - Произвольный - произвольное значение для проверки - value
//
// Возвращаемое значение:
// Булево - Это сервер
Функция ЭтоСервер(Знач Значение) Экспорт
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Main";
КонецФункции
#КонецОбласти #КонецОбласти
#КонецОбласти #КонецОбласти
@@ -527,6 +521,13 @@
КонецФункции КонецФункции
Функция ЭтоСерверИлиОбработчик(Знач Значение)
Возврат Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Server"
Или Строка(ТипЗнч(Значение)) = "AddIn.OPI_TCPServer.Handler";
КонецФункции
Процедура ОбработатьРезультат(Результат) Процедура ОбработатьРезультат(Результат)
Попытка Попытка

View File

@@ -16474,55 +16474,73 @@
TCPСервер = OPI_TCP.СоздатьСервер(7788, Истина); TCPСервер = OPI_TCP.СоздатьСервер(7788, Истина);
НовоеПодключение = OPI_TCP.ОжидатьПодключение(TCPСервер, 20); НовоеПодключение = OPI_TCP.ОжидатьВходящиеСоединения(TCPСервер, 20);
Если НовоеПодключение["result"] Тогда Если НовоеПодключение["result"] Тогда
Подключение = НовоеПодключение["connection"]["id"]; Подключение = НовоеПодключение["connection"]["id"];
Адрес = НовоеПодключение.connection.addr;
ЗапросДвочиные = OPI_TCP.ПолучитьДанные(TCPСервер, Подключение); МассивПараметровОбработки = Новый Массив;
ЗапросТекст = ПолучитьСтрокуИзДвоичныхДанных(ЗапросДвочиные); МассивПараметровОбработки.Добавить(Подключение); // Строка: "1:7788"
ОтправкаОтвета = OPI_TCP.ОтправитьДанные(TCPСервер, Подключение, ПолучитьДвоичныеДанныеИзСтроки("Yo")); ФоновоеОбработки = ФоновыеЗадания.Выполнить("OPI_Тесты.TCP_ОбработатьПодключение", МассивПараметровОбработки);
ЗакрытиеПодключения = OPI_TCP.ЗакрытьВходящееСоединение(TCPСервер, Подключение);
TCP_ОбработатьПодключение(Подключение);
КонецЕсли; КонецЕсли;
Отключение = OPI_TCP.ОтключитьСервер(TCPСервер); Отключение = OPI_TCP.ОтключитьСервер(TCPСервер);
ЗаданиеКлиента = ФоновоеКлиента.ОжидатьЗавершенияВыполнения();
// END // END
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сервер)", "TCP"); ЗаданиеКлиента = ФоновоеКлиента.ОжидатьЗавершенияВыполнения();
OPI_ПолучениеДанныхТестов.Проверка_Компонента(TCPСервер, "AddIn.OPI_TCPServer.Main"); ЗаданиеОбработки = ФоновоеОбработки.ОжидатьЗавершенияВыполнения();
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение", "TCP");
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сервер)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_Компонента(TCPСервер, "AddIn.OPI_TCPServer.Server");
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(НовоеПодключение, "ОжидатьПодключение", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(НовоеПодключение); OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(НовоеПодключение);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (подключение)", "TCP"); OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Подключение, "ОжидатьПодключение (подключение)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_Строка(Подключение, "1"); OPI_ПолучениеДанныхТестов.Проверка_Строка(Подключение, "7788:1");
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (сообщение)", "TCP"); OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Отключение, "ОжидатьПодключение (отвключение)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_Строка(ЗапросТекст, Сообщение);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (ответ)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ОтправкаОтвета);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (закрытие)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ЗакрытиеПодключения);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (отвключение)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(Отключение); OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(Отключение);
Состояние = Строка(ЗаданиеКлиента.Состояние); Состояние = Строка(ЗаданиеКлиента.Состояние);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(TCPСервер, "ОжидатьПодключение (фоновое)", "TCP"); OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Состояние, "ОжидатьПодключение (фоновое)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_Строка(Состояние, "Задание выполнено"); OPI_ПолучениеДанныхТестов.Проверка_Строка(Состояние, "Задание выполнено");
КонецПроцедуры КонецПроцедуры
Процедура TCP_ОбработатьПодключение(Подключение) Экспорт
// Подключение - Строка: "1:7788"
ЗапросДвочиные = OPI_TCP.ПолучитьЗапрос(Подключение);
ЗапросТекст = ПолучитьСтрокуИзДвоичныхДанных(ЗапросДвочиные);
ОтправкаОтвета = OPI_TCP.ОтправитьОтвет(Подключение, ПолучитьДвоичныеДанныеИзСтроки("Yo"));
ЗакрытиеПодключения = OPI_TCP.ЗакрытьВходящееСоединение(Подключение);
// END
Сообщение = "Тестовая отправка данных на сервер";
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(Сообщение, "ОжидатьПодключение (сообщение)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_Строка(ЗапросТекст, Сообщение);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(ОтправкаОтвета, "ОжидатьПодключение (ответ)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ОтправкаОтвета);
OPI_ПолучениеДанныхТестов.ЗаписатьЛог(ЗакрытиеПодключения, "ОжидатьПодключение (закрытие)", "TCP");
OPI_ПолучениеДанныхТестов.Проверка_РезультатИстина(ЗакрытиеПодключения);
КонецПроцедуры
#КонецОбласти #КонецОбласти
#Область SQLite #Область SQLite