. Итак, выше приведена часть гипертекстового содержимого, полученного из веб сайта издательства McGraw-Hill по адресу www.McGraw-Hill.com. В рассматривае мом здесь примере программы это содержимое просто выводится в исходном виде на экран посимвольно и не форматируется в удобочитаемом виде, как это обычно дела ется в окне браузера. Проанализируем данную программу построчно. Прежде всего обратите внимание на использование в ней пространства имен System.Net. Как пояснялось ранее, в этом пространстве имен находятся классы сетевого подключения к Интернету. Обратите также внимание на то, что в данную программу включено пространство имен System. 10, которое требуется для того, чтобы прочитать полученную на веб-сайте информа цию, используя объект типа Stream. В начале программы создается объект типа WebRequest, содержащий требуемый URI. Как видите, для этой цели используется метод Create(), а не конструктор. Это статический член класса WebRequest. Несмотря на то что класс WebRequest является абстрактным, это обстоятельство не мешает вызывать статический метод данного клас са. Метод Create() возвращает объект типа HttpWebRequest. Разумеется, его зна чение требуется привести к типу HttpWebRequest, прежде чем присвоить его пере менной req ссылки на объект типа HttpWebRequest. На этом формирование запроса завершается, но его еще нужно отправить по указанному URL Для того чтобы отправить запрос, в рассматриваемой здесь программе вызыва ется метод GetResponse() для объекта типа WebRequest. Отправив запрос, метод GetResponse() переходит в состояние ожидания ответа. Как только ответ будет по лучен, метод GetResponse() возвратит объект типа WebResponse, в котором инкап сулирован ответ. Этот объект присваивается переменной resp. Но в данном случае от вет принимается по протоколу HTTP, и поэтому полученный результат приводится к типу HttpWebResponse. Среди прочего в ответе содержится поток, предназначаемый для чтения данных из источника по указанному URL Далее поток ввода получается в результате вызова метода GetResponseStream() для объекта resp. Это стандартный объект класса Stream со всеми атрибутами и сред ствами, необходимыми для организации потока ввода. Ссылка на этот поток присваи вается переменной istrm, с помощью которой данные могут быть прочитаны из ис точника по указанному URI, как из обычного файла. После этого в программе выполняется чтение данных из веб-сайта издательства McGraw-Hill по адресу www.McGraw-Hill.com и последующий их вывод на экран. А поскольку этих данных много, то они выводятся на экран отдельными порциями по 400 символов, после чего в программе ожидается нажатие клавиши , чтобы продолжить вывод. Благодаря этому выводимые данные можно просматривать без прокрутки экрана. Обратите внимание на то, что данные читаются посимвольно с по мощью метода ReadByte(). Напомним, что этот метод возвращает очередной байт из потока ввода в виде значения типа int, которое требуется привести к типу char. По достижении конца потока этот метод возвращает значение -1. И наконец, ответный поток закрывается при вызове метода Close() для объекта resp. Вместе с ответным потоком автоматически закрывается и поток ввода. Ответный поток следует закрывать в промежутках между последовательными запросами. В про тивном случае сетевые ресурсы могут быть исчерпаны, препятствуя очередному под ключению к Интернету. И в заключение анализа рассматриваемого здесь примера следует обратить особое внимание на следующее: для отображения гипертекстового содержимого, получаемо го от сервера, совсем не обязательно использовать объект типа HttpWebRequest или HttpWebResponse. Ведь для решения этой задачи в данной программе оказалось до статочно стандартных методов, определенных в классах WebRequest и WebResponse, и не потребовалось прибегать к специальным средствам протокола HTTP. Следова тельно, вызовы методов Create() и GetResponse() можно было бы написать сле дующим образом. // Сначала создать объект запроса типа WebRequest по указанному URI. WebRequest req = WebRequest.Create("http://www.McGraw-Hill.com"); // Затем отправить сформированный запрос и получить на него ответ. WebResponse resp = req.GetResponse(); В тех случаях, когда не требуется приведение к конкретному типу реализации про токола, лучше пользоваться классами WebRequest и WebResponse, так как это дает возможность менять протокол, не оказывая никакого влияния на код программы. Но поскольку во всех примерах, приведенных в этой главе, используется протокол HTTP, то в ряде примеров демонстрируются специальные средства этого протокола из клас сов HttpWebRequest и HttpWebResponse. Обработка сетевых ошибок Программа из предыдущего примера составлена верно, но она совсем не защищена от простейших сетевых ошибок, которые способны преждевременно прервать ее вы полнение. Конечно, для программы, служащей в качестве примера, это не так важно, как для реальных приложений. Для полноценной обработки сетевых исключений, которые могут быть сгенерированы программой, необходимо организовать контроль вызовов методов Create(), GetResponse() и GetResponseStream(). Следует осо бо подчеркнуть, что генерирование конкретных исключений зависит от используемого протокола. И ниже речь пойдет об ошибках, которые могут возникнуть при использо вании протокола HTTP, поскольку средства сетевого подключения к Интернету, доступ ные в С#, рассматриваются в настоящей главе на примере именно этого протокола. Исключения, генерируемые методом Create() Метод Create(), определенный в классе WebRequest, может генерировать четыре исключения. Так, если протокол, указываемый в префиксе URI, не поддерживается, то генерируется исключение NotSupportedException. Если формат URI оказывает ся недействительным, то генерируется исключение UriFormatException. А если у пользователя нет соответствующих полномочий для доступа к запрашиваемому сете вому ресурсу, то генерируется исключение System.Security.SecurityException. Кроме того, метод Create() генерирует исключение ArgumentNullException, если он вызывается с пустой ссылкой, хотя этот вид ошибки не имеет непосредственного отношения к сетевому подключению. Исключения, генерируемые методом GetResponse() При вызове метода GetResponse() для получения ответа по протоколу HTTP может произойти целый ряд ошибок. Эти ошибки представлены следующими ис ключениями: InvalidOperationException, ProtocolViolationException, NotSupportedException и WebException. Наибольший интерес среди них вызывает исключение WebException. У исключения WebException имеются два свойства, связанных с сетевыми ошиб ками: Response и Status. С помощью свойства Response можно получить ссылку на объект типа WebResponse в обработчике исключений. Для соединения по протоколу HTTP этот объект описывает характер возникшей ошибки. Свойство Response объ является следующим образом. public WebResponse Response { get; } Когда возникает ошибка, то с помощью свойства Status типа WebException мож но выяснить, что именно произошло. Это свойство объявляется следующим образом: public WebExceptionStatus Status {get; } где WebExceptionStatus — это перечисление, которое содержит приведенные ниже значения. CacheEntryNotFound ConnectFailure ConnectionClosed KeepAliveFailure MessageLengthLimitExceeded NameResolutionFailure Pending PipelineFailure ProtocolError ProxyNameResolutionFailure ReceiveFailure RequestCanceled RequestProhibitedByCachePolicy RequestProhibitedByProxy SecureChannelFailure SendFailure ServerProtocolViolation Success Timeout TrustFailure UnknownError Как только будет выяснена причина ошибки, в программе могут быть предприня ты соответствующие действия. Исключения, генерируемые методом GetResponseStream() Для соединения по протоколу HTTP метод GetResponseStream() из класса WebResponse может сгенерировать исключение ProtocolViolationException, ко торое в целом означает, что в работе по указанному протоколу произошла ошибка. Что же касается метода GetResponseStream(), то это означает, что ни один из дей ствительных ответных потоков недоступен. Исключение ObjectDisposedException генерируется в том случае, если ответ уже утилизирован. А исключение IOException, конечно, генерируется при ошибке чтения из потока, в зависимости от того, как орга низован ввод данных. Обработка исключений В приведенном ниже примере программы демонстрируется обработка всевозмож ных сетевых исключений, которые могут возникнуть в связи с выполнением програм мы из предыдущего примера, в которую теперь добавлены соответствующие обработ чики исключений. // Пример обработки сетевых исключений. using System; using System.Net; using System.IO; class NetExcDemo { static void Main() { int ch; try { // Сначала создать объект запроса типа WebRequest по указанному URI. HttpWebRequest req = (HttpWebRequest) WebRequest.Create("http://www.McGraw-Hill.com"); // Затем отправить сформированный запрос и получить на него ответ. HttpWebResponse resp = (HttpWebResponse) req.GetResponse(); // Получить из ответа поток ввода. Stream istrm = resp.GetResponseStream() ; /