Ассоциация ЭБНИТ    ИРБИС-корпорация    Вики-Ирбис    Online/CHM справка Ирбис   
Опыт и разработки пользователей ИРБИС :  ИРБИС Irbis
 
Страницы: <<12345678>>
Страница: 3 из 8
Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 29, December, 2014 07:18

artgonch написал(а):
-------------------------------------------------------
> Решил я реализовать клиентскую библиотеку на Java.

Хорошее начинание! Чем больше будет разных клиентов, тем лучше для ИРБИС-сообщества. В идеале каждый сможет найти клиента под свои требования.

> Методом проб и ошибок изучаю протокол обмена между
> клиентом и сервером. Сразу же видны неточности в
> документации.

Именно поэтому я написал ИРБИС-прокси: мне нужен был простой инструмент для изучения реального ИРБИС-протокола, который, к сожалению, отличается от его официального описания.

> Но в реализации сетевых потоков в Java нет такого
> метода (ReeadToEnd). И я подозреваю, что в .NET
> реализован не лучшим образом...

В .NET нет метода ReadToEnd, это написанный мной метод-расширение, живущий в классе Utilities в сборке ManagedClient.dll smiling smiley:
static class Utilities
{
        /// <summary>
        /// Считывает из потока максимально возможное число байт.
        /// </summary>
        /// <remarks>Полезно для считывания из сети (сервер высылает
        /// ответ, после чего закрывает соединение).</remarks>
        /// <param name="stream">Поток для чтения.</param>
        /// <returns>Массив считанных байт.</returns>
        public static byte[] ReadToEnd
            (
                this Stream stream
            )
        {
            MemoryStream result = new MemoryStream();

            while (true)
            {
                byte[] buffer = new byte[10 * 1024];
                int read = stream.Read(buffer, 0, buffer.Length);
                if (read <= 0)
                {
                    break;
                }
                result.Write(buffer, 0, read);
            }

            return result.ToArray();
        }
}
Метод, конечно же, реализован далеко не оптимально. Например, при получении большого пакета с сервера происходит многократное перераспределение и копирование блоков памяти, что отрицательно сказывается на быстродействии. К тому же потребность в памяти составляет до 2 * (размер принимаемого пакета), это становится критичным при написании мобильных и встраиваемых клиентов ИРБИС.

Однако, времени, чтобы переписать этот метод, например, на связанных списках, так и не нашлось. eye rolling smiley

Важное замечание: в ИРБИС-протоколе (в подавляющем большинстве случаев) нет способа отличить обрыв соединения от корректного завершения передачи. Поэтому клиентский софт должен сам обнаруживать неполные данные и соответственно на них реагировать.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 29, December, 2014 11:51

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

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 29, December, 2014 12:12

artgonch написал(а):
-------------------------------------------------------
> Это очень странно и некрасиво... протокол требует,
> чтобы клиент сообщил серверу длину посылаемого
> пакета, а к серверу такое требование не
> предъявляют.. У меня впечатление, что протокол
> придумывал студент-троечник.

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

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

И я их (авторов сервера) вполне понимаю: например, расформатирование сотен запрошенных записей может затянуться надолго, за это время вполне может сработать тайм-аут TCP, поэтому отправка первых данных, не дожидаясь остальных выглядит вполне разумной стратегией в условиях отсутствия в протоколе сигнала от сервера «подождите, обработка ещё не завершена». Добавление же такого сигнала резко увеличивает стоимость реализации протокола, т. к. вместо простейшей схемы «запрос-ответ» возникает конечный автомат состояний, причём с обеих сторон (на сервере и на клиенте).

> А реализация чтения пакета на связанном списке -
> это хорошая идея. Не нужно выделять память сверх
> необходимого и выполнять копирование в случае
> прихода от сервера пакета большой длины.

Было бы здорово, если бы кто-нибудь реализовал оптимальный приём ответа сервера. А потом опубликовал бы как Open Source eye rolling smiley

А то у меня встраиваемый клиент то и дело не помещается в отведённые ему килобайты RAM…

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 30, December, 2014 06:18

С отправкой и чтением пакетов все в порядке. Но теперь я не могу зарегистрироваться на сервере (отрабатываю команду A). Вот пакет от клиента:

1. A
2. C
3. A
4. 436978
5. 1
6. login
7. pass
8.
9.
10.
11. pass
12. login


Вот что приходит от сервера:

1. A
2. 436978
3. 1
4. 35 {Что это такое?}
5.
6.
7.
8.
9.
10.
11. -3333 {незарегистрированный клиент}


Когда я использую те же учетные данные при подключении из Каталогизатора, все в порядке.

И еще: имеет ли значение Идентификатор пользователя? В Вашей библиотеке Вы получаете его из генератора случайных чисел. Что будет, если попытаться зарегистрироваться на сервере с одинаковыми идентификаторами?

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 30, December, 2014 08:16

artgonch написал(а):
-------------------------------------------------------
> Вот что приходит от сервера:
>
> 1. A
> 2. 436978
> 3. 1
> 4. 35 {Что это такое?}

Не знаю. smiling smiley

Это "35" появляется всякий раз, когда клиент пытается войти с неверными учётными данными.

> Когда я использую те же учетные данные при
> подключении из Каталогизатора, все в порядке.

Имейте в виду, что первые 10 служебных строк в клиентском запросе всегда кодируются в ANSI, несмотря на то, что остальные строки (с собственно данными запроса) могут быть в UTF8. У Вас логин или пароль содержит символы с кодами > 127 ?

Кстати, ответ на запрос A (содержимое серверного INI-файла) всегда приходит в кодировке ANSI (точнее, в той кодировке, в которой он хранится на сервере, а там во всех известных мне системах используется ANSI).

> И еще: имеет ли значение Идентификатор
> пользователя?

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

> В Вашей библиотеке Вы получаете его
> из генератора случайных чисел. Что будет, если
> попытаться зарегистрироваться на сервере с
> одинаковыми идентификаторами?

Сервер ответит CLIENT_ALREADY_EXISTS (-3337).

Идеологически правильная реализация клиента должна по коду ошибки -3337 генерировать новый идентификатор клиента и повторять попытку подключения.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 30, December, 2014 10:52

amironov73 написал(а):
-------------------------------------------------------
> artgonch написал(а):
> --------------------------------------------------
> -----
> > Вот что приходит от сервера:
> >
> > 1. A
> > 2. 436978
> > 3. 1
> > 4. 35 {Что это такое?}
>
> Не знаю. smiling smiley
>
> Это "35" появляется всякий раз, когда клиент
> пытается войти с неверными учётными данными.
>
> > Когда я использую те же учетные данные при
> > подключении из Каталогизатора, все в порядке.
>
> Имейте в виду, что первые 10 служебных строк в
> клиентском запросе всегда кодируются в ANSI,
> несмотря на то, что остальные строки (с собственно
> данными запроса) могут быть в UTF8. У Вас логин
> или пароль содержит символы с кодами > 127 ?

Пока я пробую передавать логин и пароль только на латинице.

Перед экспериментами я написал маленькую заглушку, к которой подсоединял клиента (АРМ Каталогизатор) и смотрел, что он посылает. Полученный массив байтов я преобразовал в строку, используя кодировку UTF-8. при этом я передавал логин и пароль на кириллице. Вот что получилось:

1. A
2. C
3, A
4. 257563
5. 1
6. ПАСС
7. АРТЕМ
8.
9.
10.
11. АРТЕМ
12. ПАСС


Т.е. первые 10 строк клиент передал серверу в кодировке UTF-8.

> Кстати, ответ на запрос A (содержимое серверного
> INI-файла) всегда приходит в кодировке ANSI
> (точнее, в той кодировке, в которой он хранится на
> сервере, а там во всех известных мне системах
> используется ANSI).
>
> > И еще: имеет ли значение Идентификатор
> > пользователя?
>
> Конкретное значение идентификатора неважно,
> главное, чтобы он был локально уникальным. Ведь
> для каждого нового запроса устанавливается новое
> TCP-подключение, так что у сервера нет никакого
> другого способа отличить одного клиента от
> другого.

Вот это номер! Видать, я плохо документацию читал. Я думал, что TCP-соединение между сервером и клиентом установлено постоянно на все время работы. Ведь установка TCP-соединения - процесс по времени довольно длительный.

А номер команды имеет значение? Или можно не увеличивать значение счетчика?

>
> > В Вашей библиотеке Вы получаете его
> > из генератора случайных чисел. Что будет, если
> > попытаться зарегистрироваться на сервере с
> > одинаковыми идентификаторами?
>
> Сервер ответит CLIENT_ALREADY_EXISTS (-3337).
>
> Идеологически правильная реализация клиента должна
> по коду ошибки -3337 генерировать новый
> идентификатор клиента и повторять попытку
> подключения.

Ну это-то как раз реализовать просто: нужно использовать в качестве ID клиента текущее время в миллисекундах. Кстати, какое-нибудь ограничение на длину идентификатора есть?



Редактировано 1 раз. Последний раз 30.12.2014 10:53 пользователем artgonch.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 30, December, 2014 11:35

artgonch написал(а):
-------------------------------------------------------
> Т.е. первые 10 строк клиент передал серверу в
> кодировке UTF-8.

Ну, UTF, так UTF, не буду спорить smiling smiley

> А номер команды имеет значение? Или можно не
> увеличивать значение счетчика?

По моим впечатлениям, сервер никак не интерпретирует номер команды. Я пробовал посылать всегда "0", и внешне это никак не сказывалось на результатах запросов.

Но в ManagedClient64 я всё-таки инкрементирую счётчик при каждом запросе. Так спокойнее. smiling smiley

> Ну это-то как раз реализовать просто: нужно
> использовать в качестве ID клиента текущее время в
> миллисекундах.

Текущее время в миллисекундах – не самый удачный выбор. Два клиента, начавшие устанавливать подключение в один и тот же момент (с точностью до миллисекунд), рискуют никогда не выйти из вечного цикла переподключений. И это не теоретический сценарий: в своём конвертере я запускаю по 4 одновременных подключения к серверу, чтобы использовать преимущества многопроцессорности.

> Кстати, какое-нибудь ограничение на
> длину идентификатора есть?

Ничто не указывает, на то, чтобы сервер ИРБИС64 как-то интерпретировал идентификатор клиента. В моих экспериментах он спокойно реагировал как на ID="635555560188417845" (количество тиков, выдаваемое операционной системой), так и на ID="2b899d32cc624d00a4cb6feb07d30ad8" (GUID, записанный без тире). Возможно, ограничения нет вообще никакого (в разумных пределах).

Так что выбирайте идентификатор по своему вкусу. Я использую идентификаторы, максимально напоминающие стандартных клиентов (вроде как замаскировался smoking smiley).

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 02, January, 2015 07:22

С Наступившим!
Ура! Уже кое-что получается. Команды регистрации, подтверждения регистрации и отмены регистрации проходят нормально. Первые 10 строк пакета, действительно, нужно кодировать в ANSI.

Теперь пробую отработать команду получения максимального MFN от сервера по имени БД. И вот тут проблема, причина которой мне непонятна. Сервер возвращает код -2222 (Wroing Protocol). Хотя я все делаю, как-будто правильно. Вот строка, которую я отсылаю. на сервер (регистрация уже прошла):
1. O
2. C
3. O
4. 35e4c209-453a-4643-827b-e31389f87e8e
5. 3
6. pass
7. login
8.
8
10.
11. RDR

Код команды - латинская "O".

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 02, January, 2015 08:42

artgonch написал(а):
-------------------------------------------------------
> Первые 10 строк пакета, действительно, нужно кодировать в ANSI.

На самом деле, всё ещё запутаннее: несмотря на то, что тела большинства запросов (таких, как поиск или расформатирование записей) кодируются в UTF, есть запросы, тело которых надо кодировать в ANSI. Например, запись текстовых файлов на сервере. Так что будьте готовы к путанице ANSI/UTF.

> Теперь пробую отработать команду получения
> максимального MFN от сервера по имени БД. И вот
> тут проблема, причина которой мне непонятна.
> Сервер возвращает код -2222 (Wroing Protocol).

Попробуйте в качестве идентификатора клиента применить строку "123456". winking smiley

> Хотя я все делаю, как-будто правильно. Вот строка,
> которую я отсылаю. на сервер (регистрация уже
> прошла):
> 1. O
> 2. C
> 3. O
> 4. 35e4c209-453a-4643-827b-e31389f87e8e
> 5. 3
> 6. pass
> 7. login
> 8.
> 8
> 10.
> 11. RDR

Похоже, серверу ИРБИС всё-таки не очень нравятся длинные идентификаторы клиентов, к тому же содержащие нецифровые символы. Где-то в глубинах серверного кода при отработке Вашего запроса вызывается функция StrToInt, которая приводит к сбою, о котором разные версии сервера рапортуют по-разному. Например, 2012.1 мне отвечает '-1111'.

Виноват, недостаточно глубоко исследовал сей аспект.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 02, January, 2015 17:29

Спасибо. Все-таки придется использовать числа, хотя GUID выглядит красивее.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 03, January, 2015 11:47

Отработал метод получения записи по ее МФН. Но до сих пор не могу разрешить проблему. Время от времени (очень часто) в ответ на запрос о прочтении записи сервер возвращает код ошибки -2222. Я грешу на идентификатор пользователя. Но не могу понять, что же не в порядке. Я получаю строку из цифр, вызывая метод получения текущего времени в миллисекундах, затем беру из строки 6 цифр справа. Идентификаторы, которые АРМы генерируют, имеют такой же формат. А вот некоторые вызовы сервер отклоняет. Преварительная регистрация проходит успешно. Последующая разрегстрация тоже. Версия сервера - 2013.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 03, January, 2015 13:22

artgonch написал(а):
-------------------------------------------------------
> Отработал метод получения записи по ее МФН. Но до
> сих пор не могу разрешить проблему. Время от
> времени (очень часто) в ответ на запрос о
> прочтении записи сервер возвращает код ошибки
> -2222. Я грешу на идентификатор пользователя.

Что заставляет Вас так думать? Вы полагаете, что появляются другие клиенты с таким идентификатором? Или сервер «забывает» идентификатор Вашего клиента? Ещё что-то?

Чисто технический вопрос: Вы получаете -2222 под отладчиком или «в свободном полёте»? Если под отладчиком, то не случается ли таймаут TCP/IP, пока Вы исследуете поведение программы? По моему опыту лучше всего исследовать результаты общения с сервером лучше всего после того, как отправлен запрос целиком, получен весь ответ сервера и соединение корректно закрыто. Это полностью снимает вопрос о непостоянстве сетевой среды.

Другой технический вопрос: Вы работаете с отдельным (тестовым) сервером, к которому больше никто (кроме Вашего клиента) не подключается? По моему опыту самый правильный подход таков: сервер стартует каждый раз снова (как обычное приложение Windows, а не как сервис), клиент подключается (не под отладчиком, но с отладочным PDB!), проделывает интересующие нас манипуляции, отключается, сбрасывает дамп (следы такого подхода видны в библиотеке), сервер останавливается. Совсем хорошо, если перед запуском сервера БД восстанавливается в заранее известное состояние. Это позволяет исключить из рассмотрения «наводки» от предыдущих сбойных сессий и от других клиентов.

> Но не могу понять, что же не в порядке.

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

Какие настройки для TCP-подключения к серверу Вы (точнее, Java Runtime) применяете? Может быть, дело в них?

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

Глупая мысль (но всё же!): может, дело в ведущих нулях, которые появляются время от времени (не реже 10% случаев) при таком подходе?

> Преварительная регистрация проходит успешно. Последующая
> разрегстрация тоже.

Есть несколько команд, которые взаимодействуют исключительно с диспетчерским процессом: регистрация/разрегистрация, NOOP, получение версии сервера или списка активных клиентов. Для них конкретное значение идентификатора клиента неважно, лишь бы он был локально-уникальным. Остальные же команды (поиск, чтение, расформатирование) инициируют взаимодействие диспетчерского процесса с рабочими процессами. Ошибка -2222 возникает при сбоях в межпроцессном взаимодействии "диспетчер-рабочий".

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 03, January, 2015 13:51

Для удобства отладки своего клиента на «игрушечном» сервере был разработан следующий "фреймворк" smiling smiley.

Во-первых, это простейшая консольная программа с лиричным названием "KillIrbis". Она пытается корректно остановить сервер ИРБИС64, запущенный как обычное приложение (т. е. из командной строки). Вот её текст:
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;

namespace KillIrbis
{
    class Program
    {
        private const int WM_QUIT = 0x0012;

        private const string DefaultProcessName = "irbis_server";

        [DllImport ( "User32.dll", SetLastError = false )]
        private static extern int PostThreadMessage
            (
                int threadId,
                int msg,
                int wParam,
                IntPtr lParam
            );

        private static bool StopProcess ( Process process )
        {
            try
            {
                foreach ( ProcessThread thread in process.Threads )
                {
                    PostThreadMessage
                        (
                            thread.Id,
                            WM_QUIT,
                            0,
                            IntPtr.Zero
                        );
                }
            }
            catch ( Exception exception )
            {
                Debug.WriteLine ( exception );
                return false;
            }

            return true;
        }

        private static bool StopProcess ( string processName )
        {
            bool result = false;

            Process[] processes = Process
                .GetProcessesByName ( processName );
            if ( processes.Length != 0 )
            {
                result = processes.All(StopProcess);
            }

            return result;
        }

        static void Main ( string[] args )
        {
            if ( args.Length > 1 )
            {
                Console.WriteLine ( "USAGE: KillIrbis [processName]" );    
                return;
            }

            string processName = DefaultProcessName;
            if ( args.Length == 1 )
            {
                processName = args [ 0 ];
            }

            Console.Write ( "Trying to stop {0}: ", processName );
            bool result = StopProcess ( processName );
            Console.WriteLine( result ? "success" : "failure" );
        }
    }
}
Для тех, кому не хочется компилировать программу самостоятельно, прилагается её исполняемый файл.

Во-вторых, это командный файл следующего содержания:
@echo off

rem Устанавливаем пути до локального сервера ИРБИС
set IRBIS=D:\IRBIS64
set DATAI=%IRBIS%\DATAI

rem Восстанавливаем базу в известное состояние
rem Предполагается, что предварительно база была сохранена в папку SAVE
copy /B /Y %DATAI%\SAVE\*.* %DATAI%\IBIS

rem Запускаем сервер
start %IRBIS%\irbis_server

rem Здесь помещаем вызов своего клиента
IrbisPing "host=127.0.0.1;port=6666;user=1;password=1;db=IBIS;arm=A;debug=clientdump.txt"

rem Завершаем сервер
KillIrbis

rem Ожидаем пользователя
pause
Отладка взаимодействия самописного клиента с сервером становится гораздо более комфортной.

Кроме того, подобный подход позволяет в полуавтоматическом режиме протестировать совместимость клиента с различными версиями сервера (установленными в различные папки).

Вложения: KillIrbis.exe (6KB)  
Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 03, January, 2015 18:38

Спасибо за помощь.

Отвечаю порядку.
1. Моя рабочая станция и сервер, на котором работает серверный компонент ИРБИСА - это разные машины. Связь достаточно надежная. Параллельно я запускаю и стандартные клиенты, они работают без сбоя.

2. В первые дни января к серверу кроме меня никто не подключается.

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

4. Вот моя тестовая программка (она 100 раз подключается к серверу, делает запрос на чтение и отключается):
IrbisClient64 client = new IrbisClient64("192.168.0.46", 6666, "login", "pass", "RDR");

for (int i = 0; i < 100; i++) {
try {
client.connect();
System.out.println(i + "] CLIENT ID: " + client.getUserId());
IrbisRecord64 record = client.readRecord(4908, false);
System.out.println("*****");
Thread.sleep(500);
} // try
catch (IrbisClient64Exception e) {
System.out.println(e.getMessage());
}
catch (InterruptedException e) {
// No-op.
}
finally {
client.disconnect();
} // finally
} // for

А вот и лог ее работы:
0] CLIENT ID: 286048
*****
1] CLIENT ID: 079418
WRONG_PROTOCOL
*****
2] CLIENT ID: 092649
WRONG_PROTOCOL
*****
3] CLIENT ID: 837102
*****
4] CLIENT ID: 909883
*****
5] CLIENT ID: 253007
*****
6] CLIENT ID: 221673
*****
7] CLIENT ID: 986519
*****
8] CLIENT ID: 908622
*****
9] CLIENT ID: 998449
*****
10] CLIENT ID: 121852
*****
11] CLIENT ID: 900760
*****
12] CLIENT ID: 643172
*****
13] CLIENT ID: 443207
*****
14] CLIENT ID: 146153
*****
15] CLIENT ID: 487900
*****
16] CLIENT ID: 657529
*****
17] CLIENT ID: 097032
WRONG_PROTOCOL
*****
18] CLIENT ID: 751710
*****
19] CLIENT ID: 871623
*****
20] CLIENT ID: 814487
*****
21] CLIENT ID: 790780
*****
22] CLIENT ID: 009939
WRONG_PROTOCOL
*****
23] CLIENT ID: 323575
*****
24] CLIENT ID: 756793
*****
25] CLIENT ID: 714315
*****
26] CLIENT ID: 815479
*****
27] CLIENT ID: 408353
*****
28] CLIENT ID: 601533
*****
29] CLIENT ID: 471064
*****
30] CLIENT ID: 731318
*****
31] CLIENT ID: 392709
*****
32] CLIENT ID: 844568
*****
33] CLIENT ID: 076672
WRONG_PROTOCOL
*****
34] CLIENT ID: 139569
*****
35] CLIENT ID: 922422
*****
36] CLIENT ID: 424544
*****
37] CLIENT ID: 999200
*****
38] CLIENT ID: 162380
*****
39] CLIENT ID: 974221
*****
40] CLIENT ID: 601875
*****
41] CLIENT ID: 962930
*****
42] CLIENT ID: 986020
*****
43] CLIENT ID: 818780
*****
44] CLIENT ID: 116208
*****
45] CLIENT ID: 636637
*****
46] CLIENT ID: 717165
*****
47] CLIENT ID: 329050
*****
48] CLIENT ID: 765083
*****
49] CLIENT ID: 599652
*****
50] CLIENT ID: 865548
*****
51] CLIENT ID: 913362
*****
52] CLIENT ID: 599842
*****
53] CLIENT ID: 701355
*****
54] CLIENT ID: 784701
*****
55] CLIENT ID: 764851
*****
56] CLIENT ID: 567517
*****
57] CLIENT ID: 437840
*****
58] CLIENT ID: 436608
*****
59] CLIENT ID: 583529
*****
60] CLIENT ID: 122213
*****
61] CLIENT ID: 575504
*****
62] CLIENT ID: 896854
*****
63] CLIENT ID: 062109
WRONG_PROTOCOL
*****
64] CLIENT ID: 815450
*****
65] CLIENT ID: 765166
*****
66] CLIENT ID: 902522
*****
67] CLIENT ID: 621805
*****
68] CLIENT ID: 192216
*****
69] CLIENT ID: 387373
*****
70] CLIENT ID: 479623
*****
71] CLIENT ID: 513521
*****
72] CLIENT ID: 165775
*****
73] CLIENT ID: 597065
*****
74] CLIENT ID: 227899
*****
75] CLIENT ID: 835592
*****
76] CLIENT ID: 202138
*****
77] CLIENT ID: 252505
*****
78] CLIENT ID: 857976
*****
79] CLIENT ID: 661736
*****
80] CLIENT ID: 535130
*****
81] CLIENT ID: 424356
*****
82] CLIENT ID: 134396
*****
83] CLIENT ID: 978302
*****
84] CLIENT ID: 198954
*****
85] CLIENT ID: 463954
*****
86] CLIENT ID: 187913
*****
87] CLIENT ID: 258831
*****
88] CLIENT ID: 910202
*****
89] CLIENT ID: 014607
WRONG_PROTOCOL
*****
90] CLIENT ID: 720107
*****
91] CLIENT ID: 360038
*****
92] CLIENT ID: 517574
*****
93] CLIENT ID: 967707
*****
94] CLIENT ID: 272869
*****
95] CLIENT ID: 813647
*****
96] CLIENT ID: 946778
*****
97] CLIENT ID: 782320
*****
98] CLIENT ID: 779599
*****
99] CLIENT ID: 630040
*****
Из протокола видно, что ни при одном подключении не был сгенерирован дубликатный идентификатор. А в чем причина таких сбоев, я ума не приложу.

Второй вариант теста: 100 подключений без смены иджентификатора (т.е. идентификатор я генерирую в конструкторе объекта, а метод connect уже пользуется готовым). Ни одного сбоя (-2222). Т.е. дело все-таки в идентификаторах...

Посмотреть бы исходники сервера, чтобы понять, откуда это вылазит.

И кто, интересно, придумал, что клиент должен сам "придумывать" свой уникальный идентификатор? Обычно, это обязанность сервера.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 03, January, 2015 19:05

artgonch написал(а):
-------------------------------------------------------
> А вот и лог ее работы:

> 1] CLIENT ID: 079418
> WRONG_PROTOCOL
> *****
> 2] CLIENT ID: 092649
> WRONG_PROTOCOL
> *****

Вы подтвердили мою догадку: идентификаторы, при которых происходит сбой, начинаются с нуля. Полагаю, что строковое значение идентификатора в некоторых ситуациях конвертируется в числовое, а затем – обратно, что приводит в конечном итоге к разнобою: ожидается "092649", а приходит "92649".

Либо убирайте нули в начале идентификатора (можно, например, всегда приписывать единицу в начале идентификатора), либо используйте схему вроде подобной:
int min = 100000; // Это примерные значения,
int max = 900000; // можете использовать другие
Random rand = new Random();
int identifier = rand.nextInt(max - min) + min;
> Посмотреть бы исходники сервера, чтобы понять,
> откуда это вылазит.

Я бы тоже хотел на них взглянуть, но, боюсь, не покажут... smiling smiley

В принципе, хватило бы публикации исходников irbis64_client.dll, так сказать, в качестве reference design. Но и этого, похоже, мы не дождёмся...

> И кто, интересно, придумал, что клиент должен сам
> "придумывать" свой уникальный идентификатор?
> Обычно, это обязанность сервера.

Авторы сервера, вестимо! smiling smiley

И всё-таки, для дальнейших экспериментов рекомендую Вам установить локальную версию сервера (подойдёт даже демонстрационная версия). Потому что мне в процессе сочинения ManagedClient64 удавалось "особо удачными" пакетами завесить сервер и оставить базу в неконсистентном состоянии (в лучшем случае – заблокированная запись или база, в худшем – необходимость пересоздания индекса или даже XRF).

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 03, January, 2015 19:21

Спасибо! Вы более внимательны, чем я. Про лидирующий 0 это верно подмечено. Сейчас попробую

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 04, January, 2015 06:14

А вот еще какая "шляпа" возникает при получении информации о версии сервера: [yadi.sk]
Этот формат отличен от того, который описан в документации...

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 04, January, 2015 06:52

artgonch написал(а):
-------------------------------------------------------
> А вот еще какая "шляпа" возникает при получении
> информации о версии сервера:
> [yadi.sk]
> Этот формат отличен от того, который описан в
> документации...

Я бы не сказал, что совсем "шляпа". Скорее, неполная документация.
До версии 2008 сервер вообще не умел рапортовать о своей версии (например, 2007 отвечает "Операция не поддерживается"), начиная с 2008.1 отвечал тремя строками, [почти] как показано в документации:
64.2008.1
1
100000
А потом перешёл на четырёхстрочный формат "Организация - Версия - Активные подключения - Лимит подключений". Просто поддерживайте оба варианта, и проблема решена.

По сравнению с теми расхождениями с документацией, которые Вам предстоит обнаружить, это – невинная детская игра в "крысу". smiling smiley

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 04, January, 2015 07:26

Но команда поиска по ключу у меня с первого раза сработала.

Кстати, о поиске. Можно ли задавать составной запрос, например,
"K=ANC and Y=VVV"
?

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 04, January, 2015 08:00

artgonch написал(а):
-------------------------------------------------------
> Но команда поиска по ключу у меня с первого раза
> сработала.

Имейте в виду, что для некоторых запросов количество найденных элементов может превышать системное ограничение (MAX_POSTINGS_IN_PACKET), так что запрос придётся повторять несколько раз (всякий раз указывая новое смещение) и «сшивать» результат. Особую пикантность процессу придаёт тот факт, что результат поиска может измениться в процессе «сшивки».

Обратите внимание, что можно запросить общее количество удовлетворяющих запросу записей без получения их списка.

> Кстати, о поиске. Можно ли задавать составной
> запрос, например,
> "K=ANC and Y=VVV"
> ?

Конечно, можно, только со звёздочкой вместо «and». Вот описание языка запросов: Язык запросов ИРБИС.



Редактировано 2 раз. Последний раз 04.01.2015 08:02 пользователем amironov73.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 04, January, 2015 14:51

спасибо.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 05, January, 2015 12:35

Отработал команду сохранения записи. Все как-будто бы нормально, но почему-то при сохранении в записи появилось поле 907 с текущей датой (это при создании новой записи). Хотя я в тестовую запись такого не добавлял. У меня такое подозрение, что был выполнен сценарий аввтоввода. Версия сервера - 2013-1 со всеми обновлениями.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 05, January, 2015 13:01

artgonch написал(а):
-------------------------------------------------------
> Отработал команду сохранения записи. Все как-будто
> бы нормально, но почему-то при сохранении в записи
> появилось поле 907 с текущей датой (это при
> создании новой записи). Хотя я в тестовую запись
> такого не добавлял. У меня такое подозрение, что
> был выполнен сценарий аввтоввода. Версия сервера -
> 2013-1 со всеми обновлениями.

Это результат работы autoin.gbl, так и должно быть, ведь он срабатывает для любых клиентов, в том числе самописных. Если autoin.gbl Вам мешает, можете временно переименовать его перед сохранением. Но я не рекомендую, это довольно плохая практика.

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



Редактировано 1 раз. Последний раз 05.01.2015 13:02 пользователем amironov73.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 05, January, 2015 13:19

amironov73 написал(а):
-------------------------------------------------------
> artgonch написал(а):
> --------------------------------------------------
> -----
> > Отработал команду сохранения записи. Все
> как-будто
> > бы нормально, но почему-то при сохранении в
> записи
> > появилось поле 907 с текущей датой (это при
> > создании новой записи). Хотя я в тестовую
> запись
> > такого не добавлял. У меня такое подозрение,
> что
> > был выполнен сценарий аввтоввода. Версия сервера
> -
> > 2013-1 со всеми обновлениями.
>
> Это результат работы autoin.gbl, так и должно
> быть, ведь он срабатывает для любых клиентов, в
> том числе самописных. Если autoin.gbl Вам мешает,
> можете временно переименовать его перед
> сохранением. Но я не рекомендую, это довольно
> плохая практика.
>
> Кстати, после сохранения записи сервер присылает
> клиенту модифицированную запись (в том числе новый
> номер версии записи). Идеологически правильно в
> этот момент соответственно менять содержимое
> сохраняемой записи, иначе последующие сохранения
> обязательно приведут к сбоям.


А я-то думал, что выполнение сценария autoin.gbl явно вызывает клиент (например, АРМ Каталогизатор).

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 06, January, 2015 06:06

Таки не могу понять, что с сохранением...
Загружаю запись по номеру, добавляю в нее поле и пытаюсь сохранить. В ответ получаю -608#32. Какая ошибка скрывается за этим кодом? Что означает число 32?

Если я после загрузки записи (по номеру, хотя это и не имеет значения) ставлю MFN в 0, а потом сохраняю, то все в порядке: сервер создает новую запись в БД, 11-ой строкой возвращает мне максимальный МФН + 1, 12-ой строкой - 335#40 (МФН только что созданной записи). А что означает 40?

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 06, January, 2015 07:04

artgonch написал(а):
-------------------------------------------------------
> Таки не могу понять, что с сохранением...
> Загружаю запись по номеру, добавляю в нее поле и
> пытаюсь сохранить. В ответ получаю -608#32. Какая
> ошибка скрывается за этим кодом?

Несовпадение версии записи.

> Что означает число 32?

Статус: последний экземпляр записи.

> Если я после загрузки записи (по номеру, хотя это
> и не имеет значения) ставлю MFN в 0, а потом
> сохраняю, то все в порядке: сервер создает новую
> запись в БД, 11-ой строкой возвращает мне
> максимальный МФН + 1, 12-ой строкой - 335#40 (МФН
> только что созданной записи). А что означает 40?

Статус: последний экземпляр записи + неактуализированная запись.

Последнее странно. Зачем при сохранении записи Вы просите сервер не актуализировать её?

Скорее всего, при сохранении записи Вы неверно сообщаете серверу номер её версии. Сервер ожидает, что присланный Вами номер версии будет равен номеру, хранящемуся в файле документов. После успешного сохранения сервер увеличивает номер версии на единицу и отправляет его вместе с модифицированной записью клиенту, чтобы тот запомнил его. При следующем сохранении клиент должен указать уже новый номер версии. И так далее.

На всякий случай: вот моя версия таблицы кодов возврата:
--------------------------------------------------------------------------------------------
|    Код | Описание                                         | Примечания                   |
--------------------------------------------------------------------------------------------
|      0 | Нормальное завершение                            |                              |
|   -100 | Заданный MFN вне пределов БД                     |                              |
|   -101 | Ошибочный размер полки                           | в IRBIS64_CLIENT.DLL         |
|   -102 | Ошибочный номер полки                            | в IRBIS64_CLIENT.DLL         |
|   -140 | MFN вне пределов БД                              |                              |
|   -141 | Ошибка чтения                                    |                              |
|   -200 | Указанное поле отсутствует                       | в IRBIS64_CLIENT.DLL         |
|   -201 | Предыдущая версия записи отсутствует             |                              |
|   -202 | Заданный термин не найден (термин не существует) |                              |
|   -203 | Последний термин в списке                        |                              |
|   -204 | Первый термин в списке                           |                              |
|   -300 | База данных монопольно заблокирована             |                              |
|   -301 | База данных монопольно заблокирована             |                              |
|   -400 | Ошибка при открытии файлов MST или XRF           |                              |
|        | (ошибка файла данных)                            |                              |
|   -401 | Ошибка при открытии файлов IFP                   |                              |
|        | (ошибка файла индекса)                           |                              |
|   -402 | Ошибка при записи                                |                              |
|   -403 | Ошибка при актуализации                          |                              |
|   -600 | Запись логически удалена                         |                              |
|   -601 | Запись физически удалена                         |                              |
|   -602 | Запись заблокирована на ввод                     |                              |
|   -603 | Запись логически удалена                         | в IRBIS64_CLIENT.DLL         |
|   -605 | Запись физически удалена                         | в IRBIS64_CLIENT.DLL         |
|   -607 | Ошибка autoin.gbl                                |                              |
|   -608 | Ошибка версии записи                             |                              |
|   -700 | Ошибка создания резервной копии                  |                              | 
|   -701 | Ошибка восстановления из резервной копии         |                              |
|   -702 | Ошибка сортировки                                |                              |
|   -703 | Ошибочный термин                                 |                              |
|   -704 | Ошибка создания словаря                          |                              |
|   -705 | Ошибка загрузки словаря                          |                              |
|   -800 | Ошибка в параметрах глобальной корректировки     |                              |
|   -801 | ERR_GBL_REP                                      |                              |
|   -802 | ERR_GBL_MET                                      |                              |
|  -1111 | Ошибка исполнения сервера (SERVER_EXECUTE_ERROR) |                              |
|  -2222 | Ошибка в протоколе (WRONG_PROTOCOL)              |                              |
|  -3333 | Незарегистрированный клиент                      |                              |
|        | (ошибка входа на сервер) (клиент не в списке)    |                              |
|  -3334 | Клиент не выполнил вход на сервер                |                              |
|        | (клиент не используется)                         |                              |
|  -3335 | Неправильный уникальный идентификатор клиента    |                              |
|  -3336 | Нет доступа к командам АРМ                       | Михайленко утверждает:       |
|        |                                                  | «список клиентов перегружен» |
|  -3337 | Клиент уже зарегистрирован                       |                              |
|  -3338 | Недопустимый клиент                              |                              |
|  -4444 | Неверный пароль                                  |                              |
|  -5555 | Файл не существует                               |                              |
|  -6666 | Сервер перегружен. Достигнуто максимальное число |                              |
|        | потоков обработки                                |                              |
|  -7777 | Не удалось запустить/прервать поток              |                              |
|        | администратора (ошибка процесса)                 |                              |
|  -8888 | Общая ошибка                                     |                              |
--------------------------------------------------------------------------------------------



Редактировано 1 раз. Последний раз 06.01.2015 07:05 пользователем amironov73.

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 06, January, 2015 14:10

Со статусом все в порядке. Я проверил. У полученной и сохраняемой записи он одинаковый. Вот какую строку я формирую для отправки на сервер:
IBIS
0
1
334#0#30#310#2#30#31904#^AABC^BDEF#30#31903#84-ФИС-123456#30#31907#^CКТ^A20150105^B1#30#31100#TEST#30#31701#^AIvanov^BA. B.

Версия записи после прочтения - 3. На сервере никто, кроме меня, не работает. Поэтому номер версии записи измениться не мог (последующие чтения эта показали).

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 06, January, 2015 14:37

artgonch написал(а):
-------------------------------------------------------
> Со статусом все в порядке. Я проверил. У
> полученной и сохраняемой записи он одинаковый. Вот
> какую строку я формирую для отправки на сервер:
> IBIS
> 0
> 1
> 334#0#30#310#2#30#31904#^AABC^BDEF#30#31903#
> 84-ФИС-123456#30#31907#^CКТ^A20150105^B1#30#31
> 100#TEST#30#31701#^AIvanov^BA. B.

Добавьте #30#31 после последнего поля. Это единственная разница, которую на данный момент мне удалось обнаружить между запросами, отсылаемыми Вашим и моим клиентом. smiling smiley

Кстати, статус "40" (последняя версия записи + не актуализировано) возвращается сервером даже в том случае, когда клиент явно просит его об актуализации. Это озадачивает. confused smiley

Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: artgonch (IP-адрес скрыт)
Дата: 06, January, 2015 14:58

Таки они там и есть. Просто я не указал их когда приводил пример запроса. На картинке видно, что эти символы присутствуют в конце строки:



Редактировано 1 раз. Последний раз 06.01.2015 15:00 пользователем artgonch.

Вложения: Безымянный.png (5.1KB)  
Re: Клиентская библиотека ИРБИС64 на языке C#
Пользователь: amironov73 (IP-адрес скрыт)
Дата: 06, January, 2015 15:41

artgonch написал(а):
-------------------------------------------------------
> Таки они там и есть. Просто я не указал их когда
> приводил пример запроса.

В данной ситуации могу посоветовать только одно: установить какой-нибудь перехватчик сетевых пакетов (хоть ИРБИС-прокси, хоть Ethereal (он же Wireshark), на Ваш выбор) и побайтово сравнить пакеты стандартных клиентов с Вашими. Скорее всего, Вы где-нибудь «не докладываете» символов перевода строки.

Анализатор сетевых протоколов, конечно, «тяжёлая артиллерия», но освоить его очень полезно. В том числе с точки зрения повышения самооценки. smiling smiley

Страницы: <<12345678>>
Страница: 3 из 8


Извините, только зарегистрированные пользователи могут писать в этом форуме.
This forum powered by Phorum.