Создаем настоящие native диапазоны явными числовыми аргументами, перечитываем обе границы после каждого setter и считаем свой включенный план. Не подключаемся к серверу и не проверяем доступность портов.
Где и как запускать
Платформа8.5.1.1343; серверный общий модуль собственной новой File CF; толстая управляемая форма отображает только восемь чисел. Runtime1C/CF/UI не выполнялись.
Подготовка
Задача: еще до любой настройки сервера найти пересечение двух предполагаемых диапазонов. Здесь числа портов — только целые числа в маленьких массивах. Мы принимаем свое правило планировщика: включаем обе границы. Это НЕ утверждение о том, как платформа фактически назначает адреса рабочим процессам.
Вручную создайте НОВУЮ пустую файловую CF только C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB. Имя конфигурации УчебныйПланДиапазонов85, РежимСовместимостиНеИспользовать, основное приложениеУправляемоеПриложение. Windows, платформа8.5.1.1343, толстый управляемый клиент. Код требует точную native строку File="путь"; и не принимает иной каталог/суффикс/формат регистрации. UUID в пути — маркер лаборатории, не UUID информационной базы.
Оставьте конфигурацию без справочников, документов и всех четырех видов регистров, без расширений. Создайте собственную роль Порты85Администратор с полными правами только этой новой CF, включая администрирование для ПолучитьПользователей. Создайте единственного собственного пользователя Порты85Ученик и назначьте роль. Реальные Users.Count1 и UUID текущего пользователя сверяются до создания диапазонов. Эти действия здесь не выполнялись; не переносите пример в рабочую УТ/КА/УНФ/БП.
Общие→ОбщиеМодули→ПланДиапазоновПамять85. СерверДа, оба клиентских контекстаНет, ГлобальныйНет, ВызовСервераНет, ПривилегированныйНет. Вставьте полный основной CODE. Только серверная процедура своей формы вызывает экспортную функцию этого модуля без внешних объектов и параметров.
Общие→ОбщиеФормы→ПроверкаДиапазонов85, управляемая форма. Создайте реквизиты До85, Изменено85, Восстановлено85, ПересечениеДо85, ПересечениеИзменено85, ПересечениеВосстановлено85, НижняяA85, ВерхняяA85 — Число, длина10, точность0. Протокол85 — Строка неограниченной длины; Остановка85 и Завершено85 — Булево с исходным значениемЛожь. Выведите восемь числовых полей и многострочный Протокол85 только для просмотра; флаги пользователю не выводите.
В этой форме добавьте единственную команду Выполнить85; свойствоДействие→обработчикВыполнить85(Команда). Создайте кнопку с Команда=Выполнить85 на командной панели. Вставьте целиком supporting module ПроверкаДиапазонов85, включая серверную процедуру. Не вызывайте обработчик вручную и не создавайте второй экземпляр формы в ходе одного протокола.
Конфигурация→Открыть модуль управляемого приложения: вставьте supporting module УправляемоеПриложение. Штатное событие ПриНачалеРаботыСистемы без параметров откроет только свою общую форму. Вручную обновите новую учебную конфигурацию и запустите Предприятие собственным пользователем в толстом управляемом клиенте. Никаких RAS, ragent, сервера1С, подключения к кластеру или свободных портов для этого memory урока не требуется.
Нажмите Выполнить85 один раз. После успеха либо исключения команда запрещает повтор. Если возник отказ, изучите точную ошибку в отладчике своего стенда; не возобновляйте выполнение после исключения и не восстанавливайте границы наугад. Для нового ручного протокола закройте собственный клиент и начните заново — никаких чужих процессов завершать не надо.
В этой работе изготовлены и статически проверены тексты, native контракты и отрицательные тесты. Файловая ИБ, CF, пользователи, обновление конфигурации, реальный запуск1С и UI здесь не создавались и не выполнялись. Ожидаемые будущие числа ниже не являются полученным runtime результатом.
Процедура ПроверитьСвойСтенд85()
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB"";" Тогда
ВызватьИсключение "Только свой точно подготовленный File-стенд 8.5.1.1343";
КонецЕсли;
Если Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("ПланДиапазоновПамять85") = Неопределено
Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("ПроверкаДиапазонов85") = Неопределено
Или Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Тогда
ВызватьИсключение "Нужны только свои общий модуль и общая форма; прикладных объектов быть не должно";
КонецЕсли;
Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
ВызватьИсключение "Собственный учебный стенд должен быть без расширений";
КонецЕсли;
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Если Текущий = Неопределено Или Пользователи.Количество() <> 1 Тогда
ВызватьИсключение "Нужен единственный реальный собственный пользователь ИБ";
КонецЕсли;
Если Текущий.Имя <> "Порты85Ученик" Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
ВызватьИсключение "Настоящий UUID текущего пользователя не совпал с собственным единственным пользователем";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьСвойДиапазон85(Диапазон, ОжидаемаяНижняя, ОжидаемаяВерхняя)
Если ТипЗнч(Диапазон) <> Тип("АдминистрированиеДиапазонПортов") Тогда
ВызватьИсключение "Нет настоящего собственного native диапазона";
КонецЕсли;
Нижняя = Диапазон.НижняяГраница;
Верхняя = Диапазон.ВерхняяГраница;
Если ТипЗнч(Нижняя) <> Тип("Число") Или ТипЗнч(Верхняя) <> Тип("Число") Тогда
ВызватьИсключение "Обе прочитанные native границы должны быть числами";
КонецЕсли;
Если Нижняя <> Цел(Нижняя) Или Верхняя <> Цел(Верхняя)
Или Нижняя < 0 Или Нижняя > 65535 Или Верхняя < 0 Или Верхняя > 65535 Или Нижняя > Верхняя Тогда
ВызватьИсключение "Нужны целые границы 0..65535 в правильном порядке";
КонецЕсли;
Если Нижняя <> ОжидаемаяНижняя Или Верхняя <> ОжидаемаяВерхняя Тогда
ВызватьИсключение "Не совпало полное ожидаемое состояние своего диапазона; продолжение запрещено";
КонецЕсли;
Возврат Новый ФиксированнаяСтруктура("Нижняя,Верхняя", Нижняя, Верхняя);
КонецФункции
Функция РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, НижняяВторого, ВерхняяВторого,
ОжидаемоеОбъединение, ОжидаемоеПересечение)
СнимокПервого = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
СнимокВторого = ПрочитатьСвойДиапазон85(Второй, НижняяВторого, ВерхняяВторого);
Если СнимокПервого.Нижняя <> ОригинальныйПервый.Нижняя Или СнимокПервого.Верхняя <> ОригинальныйПервый.Верхняя
Или СнимокВторого.Верхняя - СнимокВторого.Нижняя + 1 > 12 Тогда
ВызватьИсключение "Исходный диапазон A изменен либо диапазон B перестал быть собственным маленьким планом";
КонецЕсли;
ПервыйПлан = Новый Массив;
ВторойПлан = Новый Массив;
ОбъединенныйПлан = Новый Массив;
Для НомерПорта = СнимокПервого.Нижняя По СнимокПервого.Верхняя Цикл
ПервыйПлан.Добавить(НомерПорта);
ОбъединенныйПлан.Добавить(НомерПорта);
КонецЦикла;
Пересечение = 0;
Для НомерПорта = СнимокВторого.Нижняя По СнимокВторого.Верхняя Цикл
ВторойПлан.Добавить(НомерПорта);
Если ПервыйПлан.Найти(НомерПорта) <> Неопределено Тогда
Пересечение = Пересечение + 1;
КонецЕсли;
Если ОбъединенныйПлан.Найти(НомерПорта) = Неопределено Тогда
ОбъединенныйПлан.Добавить(НомерПорта);
КонецЕсли;
КонецЦикла;
Если ПервыйПлан.Количество() <> 10 Или ВторойПлан.Количество() <> СнимокВторого.Верхняя - СнимокВторого.Нижняя + 1
Или ОбъединенныйПлан.Количество() <> ОжидаемоеОбъединение Или Пересечение <> ОжидаемоеПересечение Тогда
ВызватьИсключение "Собственный расчет по actual readback не совпал с контрольными числами";
КонецЕсли;
Возврат Новый ФиксированнаяСтруктура("Объединение,Пересечение,КоличествоВторого",
ОбъединенныйПлан.Количество(), Пересечение, ВторойПлан.Количество());
КонецФункции
Функция ВыполнитьСвойПлан85() Экспорт
ПроверитьСвойСтенд85();
Первый = Новый АдминистрированиеДиапазонПортов(45410, 45419);
Второй = Новый АдминистрированиеДиапазонПортов(45420, 45429);
ОригинальныйПервый = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
До = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45420, 45429, 20, 0);
Если До.КоличествоВторого <> 10 Тогда
ВызватьИсключение "Исходный собственный B должен содержать десять чисел планировщика";
КонецЕсли;
Второй.НижняяГраница = 45418;
ПослеНижней = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45429, 20, 2);
Если ПослеНижней.КоличествоВторого <> 12 Тогда
ВызватьИсключение "После первого setter читаем оба actual bounds: промежуточный B содержит двенадцать чисел";
КонецЕсли;
Второй.ВерхняяГраница = 45427;
ПослеИзменения = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45427, 18, 2);
Если ПослеИзменения.КоличествоВторого <> 10 Тогда
ВызватьИсключение "После двух setter новый B снова содержит десять чисел";
КонецЕсли;
ПередВосстановлением = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45427, 18, 2);
Если ПередВосстановлением <> Неопределено Тогда
Если ПередВосстановлением.КоличествоВторого <> 10 Тогда
ВызватьИсключение "Восстановление разрешено только после полного ожидаемого собственного состояния";
КонецЕсли;
Иначе
ВызватьИсключение "Нет результата полной проверки перед восстановлением";
КонецЕсли;
Второй.ВерхняяГраница = 45429;
ПослеВерхней = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45418, 45429, 20, 2);
Если ПослеВерхней.КоличествоВторого <> 12 Тогда
ВызватьИсключение "Промежуточное восстановление верхней границы не подтверждено";
КонецЕсли;
Второй.НижняяГраница = 45420;
ПослеВосстановления = РассчитатьСвойПлан85(Первый, Второй, ОригинальныйПервый, 45420, 45429, 20, 0);
Если ПослеВосстановления.КоличествоВторого <> 10 Тогда
ВызватьИсключение "Полный исходный собственный B не восстановлен";
КонецЕсли;
ФинальныйПервый = ПрочитатьСвойДиапазон85(Первый, 45410, 45419);
Если ФинальныйПервый.Нижняя <> ОригинальныйПервый.Нижняя Или ФинальныйПервый.Верхняя <> ОригинальныйПервый.Верхняя Тогда
ВызватьИсключение "Полный исходный snapshot A должен остаться неизменным";
КонецЕсли;
Возврат Новый ФиксированнаяСтруктура("До,Изменено,Восстановлено,ПересечениеДо,ПересечениеИзменено,ПересечениеВосстановлено,НижняяA,ВерхняяA",
До.Объединение, ПослеИзменения.Объединение, ПослеВосстановления.Объединение,
До.Пересечение, ПослеИзменения.Пересечение, ПослеВосстановления.Пересечение,
ФинальныйПервый.Нижняя, ФинальныйПервый.Верхняя);
КонецФункцииПолный модуль своей формы: скалярный результат и две границы остановки
Общие → Общие формы → ПроверкаДиапазонов85 → Модуль
Толстый управляемый клиент и сервер своей формы, отдельные директивы контекста
&НаКлиенте
Процедура Выполнить85(Команда)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если Остановка85 Или Завершено85 Или ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Выполнить85 Тогда
ВызватьИсключение "Только один запуск своей команды; повтор после ошибки или успеха запрещен";
КонецЕсли;
Попытка
ВыполнитьНаСервере85();
Если Не Завершено85 Или До85 <> 20 Или Изменено85 <> 18 Или Восстановлено85 <> 20
Или ПересечениеДо85 <> 0 Или ПересечениеИзменено85 <> 2 Или ПересечениеВосстановлено85 <> 0
Или НижняяA85 <> 45410 Или ВерхняяA85 <> 45419 Тогда
ВызватьИсключение "Не подтвержден полный скалярный результат собственного memory расчета";
КонецЕсли;
Исключение
Остановка85 = Истина;
Протокол85 = "Отказ. Возможен частично измененный только свой memory B; повтора и слепого восстановления нет.";
ВызватьИсключение;
КонецПопытки;
#Иначе
ВызватьИсключение "Только собственный толстый управляемый клиент";
#КонецЕсли
КонецПроцедуры
&НаСервере
Процедура ВыполнитьНаСервере85()
Если Остановка85 Или Завершено85 Тогда
ВызватьИсключение "Серверная граница также запрещает повтор";
КонецЕсли;
Попытка
Пакет = ПланДиапазоновПамять85.ВыполнитьСвойПлан85();
Если Пакет.До <> 20 Или Пакет.Изменено <> 18 Или Пакет.Восстановлено <> 20
Или Пакет.ПересечениеДо <> 0 Или Пакет.ПересечениеИзменено <> 2 Или Пакет.ПересечениеВосстановлено <> 0
Или Пакет.НижняяA <> 45410 Или Пакет.ВерхняяA <> 45419 Тогда
ВызватьИсключение "Не совпали все восемь scalar результатов реального server readback";
КонецЕсли;
До85 = Пакет.До;
Изменено85 = Пакет.Изменено;
Восстановлено85 = Пакет.Восстановлено;
ПересечениеДо85 = Пакет.ПересечениеДо;
ПересечениеИзменено85 = Пакет.ПересечениеИзменено;
ПересечениеВосстановлено85 = Пакет.ПересечениеВосстановлено;
НижняяA85 = Пакет.НижняяA;
ВерхняяA85 = Пакет.ВерхняяA;
Протокол85 = "План с включенными границами: объединение20→18→20, пересечение0→2→0. A неизменен. Доступность портов и настройки сервера не проверялись.";
Завершено85 = Истина;
Исключение
Остановка85 = Истина;
ВызватьИсключение;
КонецПопытки;
КонецПроцедурыШтатное startup событие открывает только собственную форму
Конфигурация → Открыть модуль управляемого приложения
Толстый клиент, управляемое приложение
Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnPortRangePlanner85_d5827fb0-6c4a-4879-b9e8-73517ef85d6b\IB"";" Тогда
ВызватьИсключение "Нужна только своя новая File CF этого урока; другой формат регистрации откажет";
КонецЕсли;
ОткрытьФорму("ОбщаяФорма.ПроверкаДиапазонов85", , , Истина);
#Иначе
ВызватьИсключение "Только собственный толстый управляемый клиент 8.5.1.1343";
#КонецЕсли
КонецПроцедурыРазбор по шагам
До factories проверяем точную собственную среду. New(45410,45419) и New(45420,45429) создают новые частные объекты A и B. При чтении проверяем настоящий тип, обе границыЧисло, целочисленность, интервал0..65535, порядок и точное ожидаемое собственное состояние.
Фиксированный snapshot A получаем из двух actual native свойств, а не из заранее собранного dummy объекта. Снова читаем A и B; перечисляем реальные границы с нашим правилом включения. Два массива10/10 дают объединение20 и пересечение0. Найти может вернуть индекс0: наличие проверяется сравнением сНеопределено, не truthiness.
Сначала меняем нижнюю границу B на45418 и немедленно перечитываем ОБЕ границы обоих объектов. Промежуточный B45418..45429 имеет12 чисел, объединение20 и пересечение2. Только после этой полной проверки меняем верхнюю на45427: B10, объединение18, пересечение2.
Перед восстановлением отдельно подтверждаем целиком A и измененный B45418..45427 с расчетом18/2. Только затем возвращаем верхнююB45429, проверяем обе границы и промежуточные12/20/2; возвращаем нижнюю45420 и вновь проверяем10/20/0. При ошибке на любом setter или readback выполнение прекращается: автоматического catch-rollback нет.
В конце снова читаем обе native границы A и сравниваем с первоначальным фиксированным snapshot. Возвращаем шесть чисел расчета и две реальные границыA, не нативные объекты администрирования. Собственная форма принимает все восемь scalar значений только после проверки и запрещает повтор.
Как проверить результат
Будущий ручной протокол: итоговые объединения20→18→20 и пересечения0→2→0; A неизменен45410..45419. Между отдельными setter обязательны два промежуточных B12, объединение20, пересечение2.
Во всех шести расчетах читаются актуальные обе границы A/B. Прочитанные границы проверяются до циклов. Восстановление начинается только после нового полного собственного состояния18/2; catch не делает setters, retry или продолжение.
Source/text/static native equality/contexts/readonly/arity/aliases и negative mutants проверяются отдельно от1С runtime. Здесь sockets/RAS/cluster operations/DBwrites/UI/runtime0.
Ожидаемый результат
Ожидаемый будущий ручной результат: восемь чисел20,18,20,0,2,0,45410,45419 и протокол собственной формы. Частные native A/B полностью проверены, A сохранен и B восстановлен после успешных проверок. Реальное выполнение1С здесь не проводилось.
На что обратить внимание
Конструктор принимает два необязательных числа, но native справка не задает их default. Урок передает оба явно; не угадывает поведение пустого конструктора, дробных или перевернутых границ.
НижняяГраница и ВерхняяГраница RW. Возможная частичная ошибка не атомарна; отсутствие catch rollback намеренное. Новые объекты существуют только внутри серверной функции и не являются снимками или ссылками реального рабочего сервера.
Включение обеих границ — наша явно заданная математическая модель, не proof реальной политики распределения1С. Совпадение числа45418 в двух массивах не означает занятый или свободный TCP/UDP порт.
Здесь нет АдминистрированиеСервера, подключения к RAS, перечисления кластеров, назначения портов, socket/bind, сетевого сканирования, ОС-команд, печати и сохранения системных настроек. Проверка своего File/user не является sandbox безопасности чужой CF.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.