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

  • 9.4. Исключение EIdConnClosedGracefully

  • 9.4.1. Введение 9.4.2. Почему случаются исключения на серверах

  • 9.4.3. Почему это исключение

  • 9.4.5. А когда это ошибка

  • 10. Реализация протоколов

  • 10.1. Терминология протокола Перед обсуждением реализации протокола рассмотрим некоторые термины. 46 10.1.1. Простой текст (plain text)

  • 10.1.2. Команды (commands)

  • 10.1.4. Отклики (response)

  • 10.1.5 Переговоры (conversations)

  • 10.2.1. RFC - коды состояния

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


    Скачать 1.03 Mb.
    Название2. Техническая поддержка
    Дата02.05.2018
    Размер1.03 Mb.
    Формат файлаpdf
    Имя файлаГлубины Indy.pdf
    ТипДокументы
    #42664
    страница6 из 16
    1   2   3   4   5   6   7   8   9   ...   16
    9.3. Я должен знать это немедленно!
    Повторим, что исключение не возникает немедленно. Например, если вы вытащите сетевой кабель из платы или коммутатора, то может потребоваться минута или более.
    TCP/IP был разработан военными Америки, чтобы иметь устойчивый сетевой протокол, способный противостоять ядерным атакам. Поэтому он спроектирован так, что сеть ждет некоторое время ответов с другой стороны соединения и пытается делать повторные запросы. Вы можете детектировать разрыв соединения немедленно, но иным путем, чем это реализовано в TCP/IP. Данное детектирование может быть реализовано, но очень

    42 важно понять, почему для этого нет стандартных функций. Это понимание поможет вам понять, как это можно реализовать.
    В большинстве случаев, если вы думаете об этом, вы поймете, что данное поведение приемлемое и даже желательное.
    Тем не менее, есть ситуации, когда очень важно немедленно знать о потере соединения.
    Вообразим, что вы реализовали интерфейс между монитором сердечной деятельности и телеметрической системой. В этом случае, вы определенно желаете знать, что соединение потеряно как можно раньше.
    Если вы нуждаетесь в немедленном оповещении о разъединении, то вы должны встроить эту возможность в протокол.
    9.3.1. Keep Alives
    Keep alive (хранить живым) – это один из методов, детектирования немедленных разъединений. Keep alive реализован так, что одна сторона соединения на основе регулярного интервала посылается сообщение, такое как NOOP (No Operation – нет операции) другой стороне и всегда ожидает ответа. Если ответ не получен в течение указанного времени, то соединение считается проблематичным и уничтожается. Период таймаута достаточно короткий и определятся задачами протокола. Если вы реализуете соединение с сердечным монитором, то вы надеетесь, что указанный таймаут короче, чем таймаут для контроля температуры бочонка с пивом.
    Есть и другие преимущества при реализации системы keep alive. Во многих случаях, соединение TCP может оставаться действительным, даже если процесс перестал отвечать и принимать сообщения. В других случаях, процесс может продолжать обслуживать запросы, но скорость может быть очень низкой из-за проблем в сервисе, или из-за уменьшения полосы пропускания сети. Keep alive может определять эти ситуации и отмечать их как непригодные, хотя соединение еще существует.
    Keep alive запрос может посылаться на регулярной основе или при необходимости, когда требует определить состояние, в зависимости от требований протокола.
    9.3.2. Пинги (Pings)
    Пинги – это реализация, подобная keep alive, за исключением, что они не возвращаются в ответе на запрос. Пинги посылаются с одной стороны соединения, на другую на основе регулярного интервала. Одна сторона становится отправителем, а вторая монитором. Если в течение указанного интервала времени на мониторе, ответа не будет, то соединение считается непригодным и уничтожается.
    Пинги могут считаться аналогичными биениям сердца. Если они становятся редкими, то это означает проблему.
    9.4. Исключение EIdConnClosedGracefully
    Многих Indy пользователей беспокоит исключение EIdConnClosedGracefully, которое часто возбуждается серверами, особенно HTTP и другими серверами. Исключение
    EIdConnClosedGracefully сигнализирует, что другая сторона умышленно закрыла соединение. Это не тоже самое, как потерянное соединение, которое может появляется в

    43 случае ошибки соединения. Если другая сторона закрыла соединение и сокет пытается писать или читать из него, то возбуждается исключениеEIdConnClosedGracefully. Это подобно попытке чтения или записи в файл, который был закрыт без вашего оповещения.
    В некоторых случаях – это подлинное исключение и ваш код должен его обработать. В других случаях (обычно в серверах) это нормальное функционирование протокола и Indy обработает это за вас. Даже если Indy поймала его, когда вы работали в отладчике, то оно возбуждается в нем. Вы просто должны нажать F9 и продолжать и Indy обслужить это исключение, но отладчик постоянно надоедает вам. В том случае когда Indy ловит подобное исключение, ваши пользователи никогда не видят его в ваших программах, если только программа не запущена под отладчиком IDE.
    9.4.1. Введение
    9.4.2. Почему случаются исключения на серверах?
    Когда клиент подсоединяется к серверу, то имеются два пути к разъединению соединения:
    1. Взаимное соглашение – обе стороны согласны взаимно разъединиться, если одна из сторон попросит об этом и обе стороны явно разъединяются.
    2. Одностороннее разъединение – разъединение и оповещение другой стороны об этом.
    С помощью взаимного соглашения обе стороны знают когда разъединяться и обе явно производят разъединение. Большинство протоколов обмена, такие как Mail, News и другие разъединяются подобным образом.
    Когда клиент готов разъединиться, то он посылает команду серверу, оповещая его о своем желании. Сервер отвечает подтверждением и затем обе стороны закрывают соединение. В этих случаях исключение EIdConnClosedGracefully не возникает и если это случается, то это означает ошибку, которая должна быть соответственно обработана.
    В некоторых случаях взаимного соглашения не используется команда, но обе стороны знают когда другая может отсоединиться. Часто клиент подсоединяется, посылает одну команду, получает ответ и отсоединяется. Когда не используются явные команды для отсоединения, протокол определяет, что клиент должен отключиться от сервера после посылки команды и получения ответа. Примером этого являются некоторые протоколы времени.
    При одностороннем разъединении одна сторона просто отсоединяется. Другая сторона продолжает следить и как только определяет разрыв, то прекращает сессию. В протоколах, которые используют это, вы получите исключение EIdConnClosedGracefully и это нормальное поведение для них. Это исключение, но Indy в курсе и обработает это за вас. Протокол whois пример данного поведения. Клиент подсоединяется к серверу и посылает строку запроса. Сервер затем посылает ответ и отсоединяется. Ни каких других сигналов клиенту не посылается, просто производится разъединение.
    Протокол HTTP позволяет оба вида – разъединение по взаимному соглашению и одностороннее разъединение и поэтому понятно, почему вы видите иногда исключение
    EIdConnClosedGracefully с HTTP серверами. Протокол HTTP 1.0 работает подобно протоколу whois, в том смысле, что сервер не посылает сигнала о разъединении и клиент

    44 должен просто разъединиться после получения ответа. Клиент должен использовать новое соединение для каждого запроса.
    Протокол HTTP 1.1 позволяет в одном соединение запрашивать несколько документов.
    Тем не менее нет команды разъединения. В любое время, или клиент, или сервер могут разъединиться после получения ответов. Когда клиент разъединяется, но сервер еще продолжает воспринимать запросы, то возникает исключение EIdConnClosedGracefully. В большинстве случаев в HTTP 1.1, клиент единственный, кто разъединяется. А сервер разъединяется как сделано в части реализации протокола HTTP 1.1, если не используется установка keep alive.
    9.4.3. Почему это исключение?
    Многие пользователи комментируют, что здесь должен быть сигнал об отсоединении, а не исключение. Но это неверный подход в данном случае.
    Исключение EIdConnClosedGracefully возбуждается из ядра, глубоко внутри, в нескольких методах. Исключение EIdConnClosedGracefully в действительности исключение и в большинстве случаев должно быть поймано самым верхним уровнем для обработки.
    Исключение - это правильный путь для этого.
    9.4.4. Это ошибка?
    Не все исключения – это ошибки. Многие разработчики считают и уверены, что все исключения это ошибки. Это не так. Именно поэтому они названы исключениями, а не ошибками.
    Delphi и C++ Builder используют исключения, для обработки ошибок, элегантным путем.
    Тем не менее исключения могут использоваться не только в случае ошибок. Примером этого является EAbort. Исключения подобного рода используются для изменения потока исполнения и для связи с более высоким уровнем в программе, где они будут пойманы.
    Indy использует исключения подобным образом.
    9.4.5. А когда это ошибка?
    Когда исключение EIdConnClosedGracefully возникает на клиенте, то это является ошибкой и должно быть поймано и обработано.
    На сервере это исключение. Тем не менее иногда это ошибка и иногда это исключение. Во многих протоколах данное исключение это часть нормального функционирования протокола. Это общее поведение, и если вы не ловите EIdConnClosedGracefully на вашем сервере, то Indy сделает это. Это пометит соединение как закрытое и остановит рабочий поток, назначенный соединению. Если вы желаете, вы можете сами обработать данное исключение, иначе Indy сделает это за вас.
    9.4.6. Простое решение
    Исключение EIdConnClosedGracefully это базовый класс исключения, особенно для некоторых серверов, оно унаследовано от EIdSilentException. На закладке Language
    Exceptions tab of Debugger Options (Tools Menu) вы может добавить исключение
    EIdSilentException в список игнорируемых исключении. После этого добавленное

    45 исключение, если оно случится в коде будет обработано в программе, но отладчик не будет прерывать программу для обработки в среде.
    10. Реализация протоколов
    В Indy реализовано большинство распространенных протоколов. Но все равно бывают случаи, когда требуется реализовать протокол самостоятельно. Основная причина в необходимости реализации состоит в том, что нужный протокол отсутствует.
    Первый шаг в понимание что же надо реализовать. Имеется три базовых типа протоколов:

    Стандартный – эти протоколы относятся к Интернет стандартам. Для понимания просто найдите в RFC нужный протокол. В RFC протокол рассмотрен в подробностях.

    Пользовательский – пользовательские протоколы используются, когда отсутствует нужный протокол. Создание пользовательского протокола будет описано позже.

    Разработчика – это протоколы, предназначенные для общения с собственными системами или оборудованием. Протоколы разработчика – это пользовательский протокол, разработанный программистом, а вы общаетесь с ним. Я желаю вам удачи, поскольку большинство протоколов разработчика реализованы специалистами по оборудованию, которые имели один курс обучения в колледже и не имеют опыта разработки протоколов.
    Большинство протоколов общаются, с помощью текста, и если только у вас нет особых причин, то и вы тоже должны поступать также.
    Первым шагом построения клиента или сервера – это понять протокол. Для стандартных протоколов это может быть сделано с помощью чтения RFC. Для пользовательских протоколов вы его должны сами разработать.
    Большинство протоколов используют просто текст. Общение означает посылку команд и получение ответов, а возможно и данных. Текст делает протокол более простым для отладки и позволяется использовать любые языки программирования и операционные системы.
    Код состояния традиционно трехзначный номер. Не имеется стандарта на определение кодов состояния, но многие протоколы используют де-факто следующие соглашения:

    1xx - информационные

    2xx - успешные

    3xx – временные ошибки

    4xx – постоянные ошибки

    5xx – внутренние ошибки
    Каждой ошибке обычно назначается уникальный номер, но некоторые протоколы используют номера повторно и только предоставляют уникальный цифровой номер для каждой команды, а не протокола.
    10.1. Терминология протокола
    Перед обсуждением реализации протокола рассмотрим некоторые термины.

    46
    10.1.1. Простой текст (plain text)
    Простой текст (plain text) означает, что все команды (commands) и ответы (replies) используют только 7-битный код ASCII. Если передача данных в откликах (responses) допустима в двоичном виде, то почти все команды протокола и ответы используют простой текст. Двоичный код никогда не должен использоваться в командах и ответах, если на это не будет веских оснований.
    Использование простого текста упрощает отладку и тестирование. Это также означает переносимость между операционными системами и языками программирования.
    10.1.2. Команды (commands)
    Команда это текстовая строка, которая посылается клиентом серверу для запроса информации или выполнения определенных действий. Примеры команд: HELP, QUIT,
    LIST.
    Команды могут содержать дополнительные параметры, разделенные пробелами.
    Пример:
    GET CHARTS.DAT
    GET - это команда, а CHARTS.DAT – это параметр. В данном примере используется только один параметр, но команды могут содержать несколько параметров. Обычно параметры разделены пробелами, аналогично параметрам в DOS или в командной строке.
    Команды всегда кодируются на английском языке. Это может казаться предвзятым, тем не менее это общая практика, как в техническом мире, так и в мире бизнеса. Если английский не используется, то протокол не очень применим.
    Один из плохих примеров последствий локализации команд, является Microsoft Office.
    Microsoft Office может быть автоматизирован, с помощью OLE. Тем не менее, Microsoft локализовал имена методов и свойств объектов. Это означает, что если вы пишите приложения с помощью Microsoft Office Automation в американской версии, то ваше приложение не будет работать во французской версии.
    10.1.3. Ответы (reply)
    Ответы – это короткий ответ на посланную команду. Ответ содержит информацию о состоянии – успешно ли ошибка, и иногда содержит небольшое количество данных.
    Например, если команда GET customer.dat, вернет ответ 200 OK, это будет означать, что команда воспринята и будет обработана. Ответы обычно состоят только из одной строки, но могут состоять и из нескольких строк.
    В отличие от команд, текстовая часть ответа может быть локализована на другой язык, если она соответствует ограничению 7-бит ASCII. Поскольку протокол использует цифровую часть, а текстовая часть используется только для конечного пользователя и для отладки.
    10.1.4. Отклики (response)

    47
    Отклик – это часть данных, которая возвращается в ответ на команду. Отклики дополнительны и не присутствуют во всех команда. Отклики посылаются после ответа, для распознавание правильный ли ответ получен и какой формат этого отклика.
    Отклики могут быть текстовыми или двоичными. Если отклик текстовый, то обычно этот отклик в формате RFC откликов.
    10.1.5 Переговоры (conversations)
    Большинство протоколов аналогичны переговорам. Некоторые очень просты, а некоторые нет, но обычно они все равно в простом текстовом формате.
    Переговоры означают следующую структуру:
    1. отправка команды
    2. возврат состояния
    3. дополнительные данные отклика
    Вернем обратно к примеру получения почтовых кодов, в котором обмен выглядит следующим образом:
    Client: lookup 37642 77056
    Server: 200 Ok
    Server: 37642: CHURCH HILL, TN
    Server: 77056: HOUSTON, TX
    Server: .
    Разделив на отдельные куски, разговор будет выглядеть так:
    Команда:
    Client: lookup 37642 77056
    Ответ:
    Server: 200 Ok
    Отклик:
    Server: 37642: CHURCH HILL, TN Server: 77056: HOUSTON, TX Server: .
    Каждая из этих частей будет объяснена ниже.
    10.2 RFC - определения
    В настоящем нет действующих стандартов для терминов, обсуждаемых в данной главе.
    Тем не менее, эти термины базируются на квази-стандартах, на которых работают все тексто-ориентированые RFC протоколы.
    Единственное значимое исключение- это протокол POP3. Это мистерия, почему разработчики решили идти своим путем, вместо пути RFC. Протокол POP3 в реальности

    48 очень ограничен и не предлагает нужной дополнительной функциональности к протоколу.
    Это обычная диверсия.
    Протокол IMAP4, который был предложен как наследник POP3, продолжил эту порочную практику и так же использует не стандартный механизм. Протокол IMAP4 не получил широкого распространения и POP3 остается стандартным протоколом для почты.
    После этих двух упоминаний, текстовый протокол все еще остается квази-стандартным.
    Этот квази-стандарт общий путь посылки команды и получение ответов и откликов.
    10.2.1. RFC - коды состояния
    Коды состояния RFC имеют следующую форму:
    XXX Status Text
    Где XXX это цифровой код в диапазоне 100-599.
    Трехзначный цифровой номер означает ответ, который в ран-тайм, служит для определения результата выполнения команды. Обычно присутствует дополнительный текст, показываемый пользователю или для отладки. В этом случае, обычно используется английский язык, но может быть и локализован, если будет удовлетворять 7-битному коду
    ASCII. В некоторых случаях, когда данные короткие, данные возвращаются в дополнительном текстовом поле. В этих случаях данные все рано должны быть 7-бит
    ASCII, но протокол сам определяет язык и ограничения форматов. В большинстве случаев, эти данные языко-независимы (language neutral). Например, команда "TIME", возвращает "15:30" в дополнительном текстовом поле.
    Пример RFC ответа:
    404 No file exists
    404 это цифровой отклик и "No file exists" это дополнительное текстовое сообщение.
    Только код 404 должен быть интерпретирован программой и код 404 должен быть точно определен протоколом именно для этого. Текстовое сообщение обычно используется для отладки, ведения логов или для показа пользователю. Текстовое сообщение может иметь различные формы, от реализации к реализации и может быть локализировано на другие языки. Языки которые не соответствуют требованиям кода 7-бит ASCII должны быть транслитеризированы в английские символы.
    Цифровая часть может быть назначена любым значениям. Тем не менее существует общее соглашение:

    1xx - информационные

    2xx - успешные

    3xx – временные ошибки

    4xx – постоянные ошибки

    5xx – внутренние ошибки
    Числа обычно уникальные, но не всегда. Если вы назначите 201 для "File not found", многие команды могут отвечать этим кодом и значение всегда одно. В некоторых редких случаях, значение числа зависит от примененной команды. В этом случае, каждая команда

    49 назначает специфическое значение each command assigns specific meanings to each numeric reply.
    Цифровые коды, заканчивающие на 00, то есть 100, 200, и так далее резервированы для общих ответов, которые не имеют специального значения связанного с ними. 200 наиболее часто с "Ok".
    Коды состояния могут находиться на нескольких строках и содержать большие текстовые сообщения. В этом случае, остальные строки, за исключением последней должны содержать код символа тире сразу после номера, вместо пробела.
    Пример такого ответа:
    400-Unknown Error in critical system
    400-The server encountered an error and has no clue what caused it.
    400-Please contact Microsoft technical support, or your local
    400-tarot card reader who may be more helpful.
    400 Thank you for using our products!
    1   2   3   4   5   6   7   8   9   ...   16


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