А теперь прочитать и отобразить гипертекстовое содержимое,
полученное по указанному URI. Это содержимое выводился на экран
отдельными порциями по 400 символов. После каждой такой порции
следует нажать клавишу , чтобы вывести на экран следующую
порцию, состоящую из 400 символов. /
for (int i=1; ; i++) {
ch = istrm.ReadByte();
if(ch == -1) break;
Console.Write((char) ch);
if((i%400)==0) {
Console.Write ("\nНажмите клавишу .");
Console.ReadLine();
}
}
// Закрыть ответный поток. При этом закрывается
// также поток ввода istrm.
resp.Close();
} catch(WebException exc) {
Console.WriteLine("Сетевая ошибка: " + exc.Message +
"\nКод состояния: " + exc.Status);
} catch(ProtocolViolationException exc) {
Console.WriteLine("Протокольная ошибка: " + exc.Message);
} catch(UriFormatException exc) {
Console.WriteLine("Ошибка формата URI: " + exc.Message);
} catch(NotSupportedException exc) {
Console.WriteLine("Неизвестный протокол: " + exc.Message);
} catch(IOException exc) {
Console.WriteLine("Ошибка ввода-вывода: " + exc.Message);
} catch(System.Security.SecurityException exc) {
Console.WriteLine("Исключение в связи с нарушением безопасности: " +
exc.Message);
} catch(InvalidOperationException exc) {
Console.WriteLine("Недопустимая операция: " + exc.Message);
}
}
}
Теперь перехватываются все исключения, которые могут быть сгенерированы сете
выми методами. Так, если изменить вызов метода Create() следующим образом:
WebRequest.Create("http://www.McGraw-Hill.com/moonrocket");
а затем перекомпилировать и еще раз выполнить программу, то в результате может
быть выдано приведенное ниже сообщение об ошибке.
Сетевая ошибка: Удаленный сервер возвратил ошибку: (404) Не найден.
Код состояния: ProtocolError
На веб-сайте по адресу www.McGraw-Hill.com отсутствует раздел moonrocket, и
поэтому он не найден по указанному URI, что и подтверждает приведенный выше ре
зультат.
Ради краткости и ясности в программах большинства примеров из этой главы от
сутствует полноценная обработка исключений. Но в реальных приложениях она про
сто необходима.
Класс Uri
Как следует из табл. 26.1, метод WebRequest.Create() существует в двух вариан
тах. В одном варианте он принимает идентификатор URI в виде строки. Именно этот
вариант и был использован в предыдущих примерах программ. А во втором вариан
те этот метод принимает идентификатор URI в виде экземпляра объекта класса Uri,
определенного в пространстве имен System. Класс Uri инкапсулирует идентифика
тор URL Используя класс Uri, можно сформировать URI, чтобы затем передать этот
идентификатор методу Create(). Кроме того, идентификатор URI можно разделить
на части. Для выполнения многих простых операций в Интернете класс Uri малопри
годен. Тем не менее он может оказаться весьма полезным в более сложных ситуациях
сетевого подключения к Интернету.
В классе Uri определяется несколько конструкторов. Ниже приведены наиболее
часто используемые конструкторы этого класса.
public Uri(string uriString)
public Uri(Uri baseUri, string relativeUri)
В первой форме конструктора объект класса Uri создается по идентификатору URI,
заданному в виде строки uriString. А во второй форме конструктора он создается по
относительному URI, заданному в виде строки relativeUri относительно абсолютно
го URI, обозначаемого в виде объекта baseUri типа Uri. Абсолютный URI определяет
полный адрес URI, а относительный URI — только путь к искомому ресурсу.
В классе Uri определяются многие поля, свойства и методы, оказывающие помощь
в управлении идентификаторами URI или в получении доступа к различным частям
URI. Особый интерес представляют приведенные ниже свойства.
Перечисленные выше свойства полезны для разделения URI на составные части. При
менение этих свойств демонстрируется в приведенном ниже примере программы.
// Пример применения свойств из класса Uri.
using System;
using System.Net;
class UriDemo {
static void Main() {
Uri sample = new
Uri("http://HerbSchildt.com/somefile.txt?SomeQuery");
Console.WriteLine("Хост: " + sample.Host);
Console.WriteLine("Порт: " + sample.Port);
Console.WriteLine("Протокол: " + sample.Scheme);
Console.WriteLine("Локальный путь: " + sample.LocalPath);
Console.WriteLine("Запрос: " + sample.Query);
Console.WriteLine("Путь и запрос: " + sample.PathAndQuery);
}
}
Эта программа дает следующий результат.
Хост: HerbSchildt.com
Порт: 80
Протокол: http
Локальный путь: /somefile.txt
Запрос: ?ScmeQuery
Путь и запрос: /somefile.txt?SomeQuery
Доступ к дополнительной информации,
получаемой в ответ по протоколу HTTP
С помощью сетевых средств, имеющихся в классе HttpWebResponse, можно по
лучить доступ к другой информации, помимо содержимого указываемого ресурса.
К этой информации, в частности, относится время последней модификации ресурса,
а также имя сервера. Она оказывается доступной с помощью различных свойств, свя
занных с подучаемым ответом. Все эти свойства, включая и те что, определены в классе
WebResponse, сведены в табл. 26.5. В приведенных далее примерах программ демон
стрируется применение этих свойств на практике.
Свойство Описание
public string Host { get; } Получает имя сервера
public string LocalPath { get; } Получает локальный путь к файлу
public string. PathAndQuery { get; }
public int Port { get; }
Получает абсолютный путь и строку запроса
Получает номер порта для указанного про
токола. Так, для протокола HTTP номер порта
равен 80
public string Query { get; } Получает строку запроса
public string Scheme { get; } Получает протокол
Доступ к заголовку
Для доступа к заголовку с информацией, получаемой в ответ по протоколу HTTP,
служит свойство Headers, определенное в классе HttpWebResponse.
public WebHeaderCollection Headers{ get; }
Заголовок протокола HTTP состоит из пар "имя-значение", представленных строка
ми. Каждая пара "имя-значение" хранится в коллекции класса WebHeaderCollection.
Эта коллекция специально предназначена для хранения пар "имя-значение" и приме
Таблица 26.5. Свойства, определенные в классе HttpWebResponse
Свойство Описание
public string CharacterSet { get; } Получает название используемого набора
символов
public string ContentEncoding
{ get; }
Получает название схемы кодирования
public long ContentLength { get; } Получает длину принимаемого содержимого.
Если она недоступна, свойство имеет значе
ние -1
public string ContentType { get; } Получает описание содержимого
public CookieCollection Cookies
{ get; set; }
Получает или устанавливает список cookie-
наборов, присоединяемых к ответу
public WebHeaderCollection
Headers{ get; }
Получает коллекцию заголовков, присоединяе
мых к ответу
public bool IsFromCache { get; } Принимает логическое значение true, если
запрос получен из кеша. А если запрос достав
лен по сети, то принимает логическое значе
ние false
public bool
IsMutuallyAuthenticated { get; }
Принимает логическое значение true, если
клиент и сервер опознают друг друга, а ина
че — принимает логическое значение false
public DateTime LastModified { get; } Получает время последней модификации ре
сурса
public string Method { get; } Получает строку, которая задает способ ответа
public Version ProtocolVersion
{ get; }
Получает объект типа Version, описываю
щий версию протокола HTTP, используемую в
транзакции
public Uri ReponseUri { get; } Получает URI, по которому был сформирован
ответ. Этот идентификатор может отличаться от
запрашиваемого, если ответ был переадресо
ван по другому URI
public string Server { get; } Получает строку, обозначающую имя сервера
public HttpStatusCode StatusCode
{ get; }
Получает объект типа HttpStatusCode, опи
сывающий состояние транзакции
public string StatusDescription
{ get; }
Получает строку, обозначающую состояние
транзакции в удобочитаемой форме
няется аналогично любой другой коллекции (подробнее об этом см. в главе 25). Стро
ковый массив имен может быть получен из свойства AllKeys, а отдельные значения —
по соответствующему имени при вызове метода GetValues(). Этот метод возвращает
массив строк, содержащий значения, связанные с заголовком, передаваемым в качестве
аргумента. Метод GetValues() перегружается, чтобы принять числовой индекс или
имя заголовка.
В приведенной ниже программе отображаются заголовки, связанные с сетевым ре
сурсом, доступным по адресу www.McGraw-Hill.com.
// Проверить заголовки.
using System;
using System.Net;
class HeaderDemo {
static void Main() {
// Создать объект запроса типа WebRequest по указанному URI.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create("http://www.McGraw-Hill.com");
// Отправить сформированный запрос и получить на него ответ.
HttpWebResponse resp = (HttpWebResponse)
req.GetResponse();
// Получить список имен.
string[] names = resp.Headers.AllKeys;
// Отобразить пары "имя-значение" из заголовка.
Console.WriteLine("{0,-20}(1}\n", "Имя", "Значение");
foreach(string n in names) {
Console.Write("{0,-20}", n);
foreach(string v in resp.Headers.GetValues(n))
Console.WriteLine(v);
}
// Закрыть ответный поток.
resp.Close();
}
}
Ниже приведен полученный результат. Не следует забывать, что информация в заго
ловке периодически меняется, поэтому у вас результат может оказаться несколько иным.
Имя Значение
Transfer-encoding chunked
Content-Type text/html
Date Sun, 06 Dec 2009 20:32:06 GMT
Server Sun-ONE-Web-Server/6.1
Доступ к cookie-наборам
Для доступа к cookie-наборам, получаемым в ответ по протоколу HTTP, слу
жит свойство Cookies, определенное в классе HttpWebResponse. В cookie-наборах
содержится информация, сохраняемая браузером. Они состоят из пар "имя-значение"
и упрощают некоторые виды доступа к веб-сайтам. Ниже показано, каким образом
определяется свойство Cookies.
public CookieCollection Cookies { get; set; }
В классе CookieCollection реализуются интерфейсы ICollection и
IEnumerable, и поэтому его можно использовать аналогично классу любой другой
коллекции (подробнее об этом см. в главе 25). У этого класса имеется также индекса
тор, позволяющий получать cookie-набор по указанному индексу или имени.
В коллекции типа CookieCollection хранятся объекты класса Cookie. В классе
Cookie определяется несколько свойств, предоставляющих доступ к различным фраг
ментам информации, связанной с cookie-набором. Ниже приведены два свойства, Name
и Value, используемые в примерах программ из этой главы.
public string Name { get; set; }
public string Value { get; set; }
Имя cookie-набора содержится в свойстве Name, а его значение — в свойстве
Value.
Для того чтобы получить список cookie-наборов из принятого ответа, необходимо
предоставить cookie-контейнер с запросом. И для этой цели в классе HttpWebRequest
определяется свойство CookieContainer, приведенное ниже.
public CookieContainer CookieContainer { get; set; }
В классе CookieContainer предоставляются различные поля, свойства и методы,
позволяющие хранить cookie-наборы. По умолчанию свойство CookieContainer
содержит пустое значение. Для того чтобы воспользоваться cookie-наборами, необ
ходимо установить это свойство равным экземпляру класса CookieContainer. Во
многих приложениях свойство CookieContainer не применяется непосредственно,
а вместо него из принятого ответа составляется и затем используется коллекция типа
CookieCollection. Свойство CookieContainer просто обеспечивает внутренний
механизм сохранения cookie-наборов.
В приведенном ниже примере программы отображаются имена и значения cookie-
наборов, получаемых из источника по URI, указываемому в командной строке. Следу
ет, однако, иметь в виду, что cookie-наборы используются не на всех веб-сайтах, поэто
му нужно еще найти такой веб-сайт, который поддерживает cookie-наборы.
/