Главная страница
Навигация по странице:

  • 12.1.2. Компонент TIdIOHandlerStream

  • 12.1.3. Компонент TIdSSLIOHandlerSocket

  • 12.2. Пример - Speed Debugger

  • 12.2.1. Пользовательский обработчик IOHandler

  • 13.2. Ведение логов (Logging)

  • 14.3. Запись и воспроизведение

  • 15. Параллельное выполнение (Concurrency)

  • 15.1. Терминология 63 15.1.1. Параллельное выполнение

  • 15.1.2. Борьба (споры) за ресурсы (Contention)

  • 15.1.3. Защита ресурсов (Resource Protection)

  • 15.2. Разрешение споров (Resolving Contention)

  • 15.2.1. Только чтение (Read Only)

  • 15.2.2. Атомарные операции (Atomic Operations)

  • 15.2.3. Поддержка Операционной Системы (Operating System Support)

  • Глубины Indy. 2. Техническая поддержка


    Скачать 1.03 Mb.
    Название2. Техническая поддержка
    Дата02.05.2018
    Размер1.03 Mb.
    Формат файлаpdf
    Имя файлаГлубины Indy.pdf
    ТипДокументы
    #42664
    страница8 из 16
    1   ...   4   5   6   7   8   9   10   11   ...   16
    12.1. Компоненты IOHandler
    12.1.1. Компонент TIdIOHandlerSocket
    Компонент TIdIOHandlerSocket это обработчик IOHandler по умолчанию. Если обработчик не указан явно, то он создается неявно для вас. Компонент TIdIOHandlerSocket обрабатывает весь ввод/вывод, относящийся к TCP сокетам.
    Обычно, компонент TIdIOHandlerSocket не используется явно, пока не потребуются расширенные способности.
    12.1.2. Компонент TIdIOHandlerStream
    Компонент TIdIOHandlerStream используется для отладки и тестирования. При его использовании все взаимодействие с сервером в TCP сессии может быть записаны. Позже вся сессия может быть «проиграна». Компоненты Indy не знают, работают ли они с реальным сервером и реальным соединением.
    Это очень мощное средство отладки в дополнение к инструменту QA отладки. Если у пользователя есть проблемы, то специальная версия программы может быть послана пользователю или включены средства отладки для ведения лога сессии. Используя лог файлы, вы можете затем реконструировать сессию пользователя в локальной отладочной среде.
    12.1.3. Компонент TIdSSLIOHandlerSocket
    Компонент TIdSSLIOHandlerSocket используется для поддержки SSL. Обычно компрессия и декомпрессия данных может быть реализована с использованием перехватчиков
    (Intercepts) вместо IOHandlers. Но SSL библиотека используемая Indy (OpenSSL), работает напрямую с сокетом, вместо трансляции данных посылаемых Indy. Поэтому реализация выполнена как IOHandler. . TIdSSLIOHandlerSocket является наследником
    TIdIOHandlerSocket.
    12.2. Пример - Speed Debugger
    Пример Speed Debugger демонстрирует как симулировать медленное соединение. Это полезно, как для отладки, так и для тестирования ваших приложений при симуляции медленных сетей, таких как модемы.
    Пример Speed Debugger состоит из главной формы и пользовательского обработчика
    IOHandler. Speed Debugger использует компонент «маппированый порт» для передачи

    59 данных конкретному web серверу. Браузер соединяется со Speed Debugger и Speed
    Debugger пробует получить страницу с указанного web сервера, затем возвращает ее web браузеру замедленно, с указанной скоростью.
    Поле текстового ввода используется для указания web сервера.
    Примечание: не указывайте URL и не указывайте протокол http:// или web страницу. Оно предназначено только для указания имени сервера или его IP адреса. Если у вас есть локальный web сервер, то вы можете просто указать 127.0.0.1 и использовать локальный web сервер.
    Комбо-бокс используется для выбора скорости и состоит из следующих выборов.
    Симулируемая скорость указывается в скобках.

    Apache (Unlimited)

    Dial Up (28.8k baud)

    IBM PC XT (9600 baud)

    Commodore 64 (2400 baud)

    Microsoft IIS on a PIII-750 & 1GB RAM (300 baud)
    После нажатия кнопки Test - Speed Debugger загружает браузер по умолчанию с URL http://127.0.0.1:8081/. В данном случае браузер делает запрос из Speed Debugger. Speed
    Debugger слушает на порту 8081, который может конфликтовать с некоторым существующими локальными web серверами.
    Пример Speed Debugger может быть загружен с Indy Demo Playground.
    12.2.1. Пользовательский обработчик IOHandler
    Работа Speed Debugger делается на основе пользовательского IOHandler. Маппированый порт компонент имеет событие OnConnect, и данное событие используется как хук в нашем IOHandler для каждого исходящего клиента, который создает маппированый порт.
    Это выглядит так: procedure TformMain.IdMappedPortTCP1Connect(AThread: TIdMappedPortThread);
    var
    LClient: TIdTCPConnection;
    LDebugger: TMyDebugger;
    begin
    LClient := AThread.OutboundClient;
    LDebugger := TMyDebugger.Create(LClient);
    LDebugger.BytesPerSecond := GSpeed;
    LClient.IOHandler := LDebugger;
    end
    ;
    Пользовательский класс IOHandler, называется TMyDebugger и реализован как наследник от TIdIOHandlerSocket, являющегося наследником IOHandler. Поскольку
    TIdIOHandlerSocket уже реализует весь актуальный ввод/вывод, TMyDebugger должен только замедлить передачу данных. Это делается путем перекрытия метода Recv.
    Из метода Recv вызывается наследованный Recv для приема данных. Затем, базируясь на выбранном ограничении скорости, рассчитывается необходимая задержка. Если рассчитанная величина больше, чем наследованная, то метод Recv вызывает Sleep. Это может казаться сложным, но на самом деле это очень просто. Метод Recv приведен ниже.

    60 function TMyDebugger.Recv(var ABuf; ALen: integer): integer;
    var
    LWaitTime: Cardinal;
    LRecvTime: Cardinal;
    begin
    if
    FBytesPerSecond >
    0
    then
    begin
    LRecvTime := IdGlobal.GetTickCount;
    Result :=
    inherited
    Recv(ABuf, ALen);
    LRecvTime := GetTickDiff(LRecvTime, IdGlobal.GetTickCount);
    LWaitTime := (Result *
    1 000) div FBytesPerSecond;
    if
    LWaitTime > LRecvTime
    then
    begin
    IdGlobal.Sleep(LWaitTime – LRecvTime);
    end
    ;
    end
    else
    begin
    Result :=
    inherited
    Recv(ABuf, ALen);
    end
    ;
    end
    ;
    13. Перехватчики (Intercepts)
    Перехватчик – это более высокий уровень, чем обработчик ввода/вывода и используется для модификации или перехвата данных независимо от источника и приемника.
    Перехватчики были сильно изменены в версии 9.0. В версии 8.0 перехватчик мог предоставлять только весьма ограниченную функциональность обработчика ввода/вывода. Перехватчики могут трансформировать уже принятые данные или данные для передачи. Перехватчики более не поддерживают никакой функциональности обработчика ввода/вывода (IOHandler), поскольку введены новые классы IOHandler, со всей необходимой функциональностью.
    Перехватчики попрежнему могут выполнять преобразования данных и но предоставляют больше возможностей в Indy 9.0. Возможности трансформация в Indy 8.0 были сильно ограничены, так как данные должны были иметь один и тот же размер. Это делало невозможным использовать их для реализации сжатия данных или логирования, поскольку не позволяло изменить размер данных.
    Перехватчики позволяют изменять данные после того, как они были приняты в IOHandler или изменять их перед посылкой в IOHandler. Перехватчики в данный момент используются для реализации ведения логов и отладки компонент. Они могут быть также использованы для реализации шифрования, сжатия, статических коллекторов или ограничитения трафика.
    13.1. Перехватчики
    Перехватчики взаимодействуют с входящими или исходящими данными и позволяют их записывать в лог или модифицировать. Перехватчики позволяют изменять входящие данные, после того как они приняты из сети, перед выдачей их пользователю.
    Перехватчики также позволяют модифицировать исходящие данные перед посылкой в сеть. Перехватчики могут быть использоваться для реализации ведения логов, шифрования и сжатия данных.

    61
    Клиентские перехватчики базируются на соединениях (по одному на каждое). Они также могут быть использованы на сервере, если они назначены индивидуальному соединению.
    Примечание: Перехватчики в Indy 9 отличаются от перехватчиков в Indy 8. Перехватчики в Indy 8, выполняли комбинированную роль перехватчика и обработчика ввода/вывода.
    Что делало сложным разделение функций перехвата и обработки. Перехватчики Indy 8 также не могли изменять размер данных и поэтому были непригодны для сжатия.
    13.2. Ведение логов (Logging)
    Indy 8.0 имел один компонент ведения логов, который мог быть использован для различных источников. В Indy 9.0 компоненты логов теперь базируются на новом общем классе и имеют специализированные классы. Базовый класс также предоставляет свойства и функциональность, такую как регистрация времени, в дополнение к данным.
    Все классы ведения логов реализованы, как перехватчики. Это означает, что они перехватывают входящие данные, после того, как они были прочитаны и перед передачей исходящих в источник.
    Специализированные классы логов, следующее:

    TIdLogEvent – возбуждает события, когда данные приняты, или переданы, или при появлении события состояния. Класс TIdLogEvent полезен для реализации пользовательских логов, без необходимости в реализации нового класса.

    TIdLogFile – Записывает данные в файл.

    TIdLogDebug – Записывает данные в окно отладки Windows или в консоль Linux.
    Также отмечает данные, как принятые данные, переданные данные или информация о статусе. Класс TidLogDebug полезен для проведения простой отладки.

    TIdLogStream – Не добавляет комментариев, отметок к данным, как другие классы.
    Вместо этого просто записывает сырые данные в указанный поток. Класс
    TIdLogStream может использоваться по разному, но обычно он очень эффективно используется для QA тестирования и удаленной отладки. Могут быть построены и пользовательские классы логов.
    14. Отладка
    Обычно отладка клиентов проще отладки серверов. Клиенты просто должны обслуживать только одно соединение и могут обычно быть отлажены с помощью простой техники отладки. В данной главе приводится несколько полезных советов для отладки клиентов и серверов.
    14.1. Ведение логов
    Реально простой путь – что увидеть, что делает клиент, без трассировки по коду – это использовать классы TIdLogDebug или TIdLogFile. Класс TIdLogDebug выводит информацию в напрямую в окно отладки и очень удобен для наблюдения, того, что клиент посылает и принимает в реальном масштабе времени. Если вы не желает смотреть трафик в реальном времени, то воспользуйтесь классом TIdLogFile. После того как клиент

    62 закончит свою работу, вы можете посмотреть содержимое файла и увидеть, что делалось во время сессии.
    14.2. Симуляция
    Но иногда требуется симулировать клиента или сервер, если он не доступен. Это может быть сделано по причинам безопасности, трафика или по другим причинам. В таких случаях вы можете воспользоваться симуляцией. Симуляция может также использоваться для построения клиента, до построения сервера или для создания тестовых скриптов, путем симуляции клиента.
    Симуляция может быть выполнена с помощью TIdIOHandlerStream и назначения потока вывода в текстовый файл, поток ввода должен быть установлен в nil. Это указывает классу TIdIOHandlerStream читать все данные для посылки клиенту из текстового файла и игнорировать все данные возвращаемые с клиента.
    Если вы назначите поток ввода, то будет происходить ведение лога с данными клиента.
    14.3. Запись и воспроизведение
    Одним из полезных методов является запись сессии, и последующего ее воспроизведения.
    Это особо востребовано для регрессивного тестирования и удаленной отладки. Если ваш заказчик находится в удаленном месте, то вы можете послать ему особую версию программы или включить запись сессии. Затем они могут вам переслать записанный файл, и вы сможете симулировать его сессию клиента или сервер у себя на месте, без необходимости иметь реальное соединение с их сервером.
    Для выполнения этого используйте класс TIdLogStream для записи принятых данных в файл. Вы сможете также записать данные, которые клиент передавал в отдельный файл, но вы не нуждаетесь в этом, пока не потребуется их посмотреть вручную. После того, как вы получите файл, вы можете его подсоединить к компоненту TIdIOHandlerStream.
    Обработчики ввода/вывода (IOHandlers) также имеют другое полезное применение. Они используются для записи и воспроизведения. Живая сессия может быть записана с помощью компонентов ведения логов и позже воспроизведена с помощью потоков обработчиков ввода/вывода. Представим, что вы имеет заказчика, у которого есть проблемы, но вы не можете воспроизвести эти проблемы у себя и не можете посетить его.
    Вы можете попросить его прислать лог полной сессии и попытаться воспроизвести сессию на вашей машине. Команда Indy использует это как часть своей QA отладки. Я планирую описать это позже.
    15. Параллельное выполнение (Concurrency)
    В многопоточной среде ресурсы должны быть защищены так, чтобы они не были разрушены при одновременном доступе.
    Параллельное выполнение и потоки переплетаются и выбор, что изучать сначала может быть сложным. В данном разделе мы рассмотрим параллельное выполнение и попытаемся дать понятия для изучения потоков.
    15.1. Терминология

    63
    15.1.1. Параллельное выполнение
    Параллельное выполнение – это состояние, когда много задач возникает в одно и тоже время. Когда конкурирование реализовано правильно это может рассматривать как
    «гармония», а если плохо, то как «хаос».
    В большинстве случаев, задача выполняется в потоке (thread). Но также это могут быть процессы (process) или волокна (fiber). Разделение очень условное, но использование правильной адстракции является ключем к успеху.
    15.1.2. Борьба (споры) за ресурсы (Contention)
    Что же такое точно борьба за ресурсы? Борьба за ресурсы – это когда более чем одна задача пытается получить доступ к одному и тому же ресурсу, в то же самое время.
    Для тех, кто живет в большой семье обычно понятно, о чем идет речь, и может дать пример споров. Представим себе семью с шестью маленькими детьми, когда мама ставит на сто маленькую пиццу. Будет драка.
    Когда множеству конкурирующих задач требуется доступ к данным режиме чтения/записи, то данные должны быть защищены. Если доступ не контролируется, две или более задач могут разрушить их, когда одна задача пытается писать, а другая читать одновременно. Если одна задача записывает во время чтения другой, то возможно чтение и запись несогласованных данных.
    Обычно в этом случае не возникает исключения, и ошибка проявится позже в программе.
    Проблемы борьбы за ресурсы не возникают в приложениях при малой нагрузке и поэтому не обнаруживают себя во время разработки. По этому правильное тестирование должно производиться на большой нагрузке. Иначе это подобно «русской рулеткe» и проблемы будут возникать редко во время разработки и часто в рабочей среде.
    15.1.3. Защита ресурсов (Resource Protection)
    Защита ресурсов – это способ разрешения проблемы борьбы за ресурсы. К функциям защиты ресурсов относится разрешение доступа только одной задаче в одно и то же время.
    15.2. Разрешение споров (Resolving Contention)
    Когда множеству потоков требуется доступ до ресурсов в режиме чтения/записи, данные должны контролироваться для защиты их целостности. Это может наводить ужас на программиста не умеющего работать с потоками.
    Как правило, большинство серверов не нуждаются в глобальных данных. Обычно им требуется читать данные только во время инициализации программы. Так как здесь нет доступа по записи потоки могут читать глобальные данные без побочных эффектов.
    Общие пути разрешения споров приведены ниже.
    15.2.1. Только чтение (Read Only)

    64
    Самый простой метод – это режим только чтение. Все простые типы (integers, strings, memory), которые используются в режиме только чтения - не требуют защиты. Это также относится и к таким сложным типам как TList и другие. Классы безопасны если только не используют глобальные переменные или глобальные поля классов в режиме чтения/записи.
    В дополнение, ресурсы должны быть записаны перед любыми попытками чтения. Это делается путем инициализацией ресурсов во время запуска, до того как задачи будут к ним обращаться.
    15.2.2. Атомарные операции (Atomic Operations)
    Методология утверждает, что атомарные операции не требуют защиты. Атомарные операции – это такие операции, которые очень малы для деления в процессоре.
    Поскольку, их размер маленький, то это не приводит к спорам, так как они выполняются разом и не могут быть прерваны во время исполнения. Обычно атомарные операции – это строки кода компилируемые в одну иструкцию ассемблера.
    Обычно задачи, такие как чтение или запись целых чисел (integer) или логических полей
    (boolean field) являются атомарными операциями, так как они выполняются с помощью единственной инструкции move. Тем не менее моя рекомендация, такая – никогда не рассчитывайте на атомарность операций, поскольку в некоторых случаях, даже при записи целого (integer) или логического (Boolean) может быть выполнено более одной инструкции, в зависимости от того, откуда данные читались. В дополнение, это требует знания внутренней природы компилятора, которое является предметом для изменения в любое время, без вашего оповещения. Закладываясь на атомарные операции вы можете написать код, который будет неоднозначным в некоторых случаях и может работать по разному на многопроцессорных машинах или других операционных системах.
    Я до недавнего времени считал атомарные операции очень защищенными. Тем не менее, приход .NET принесет серьезную проблему. Когда наш код был компилирован в IL, и затем перекомпилирован в машинный код на платформах различных производителей, можете ли вы быть уверены, что каждая строка вашего кода будет атомарной операцией в конце концов?
    Выбор конечно ваш, и конечно есть аргументы как за, так и против атомарных операций.
    Атомарные операции в большинстве случаев сохраняют только несколько микросекунд и несколько байт кода. Я настоятельно рекомендую не использовать атомарные операции, так как они дают мало преимуществ и являются потенциальным источником неприятонстей.
    15.2.3. Поддержка Операционной Системы (Operating System Support)
    Многие операционные системы имеют поддержку базовых потоко-безопасных операций.
    Windows поддерживает набор функций, известных как, блочные (Interlocked) функции.
    Польза от этих функций очень маленькая и состоит в поддержке только простой функциональности для целых чисел, как увеличение, уменьшение, добавление, обмен и обмен со сравнением.

    65
    Количество функций варьируется от версии Windows и может быть причиной замораживания (deadlocks) в старых версиях Windows. В большинстве приложений они имеют малые плюсы.
    Поскольку их функциональность ограничена, не поддерживается повсюду, и дает лишь некоторое увеличение производительности, вместо них в Indy рекомендуется использовать потоко-безопасные эквиваленты (заменители). (threadsafe).
    Windows также имеет поддержку объектов IPC (interprocess communication), обертка вокруг которых имеется в Delphi. Данные объекты особенно полезны для программирования потоков и IPC.
    1   ...   4   5   6   7   8   9   10   11   ...   16


    написать администратору сайта