Текст книги "C# 4.0: полное руководство"
Автор книги: Герберт Шилдт
Жанр:
Программирование
сообщить о нарушении
Текущая страница: 81 (всего у книги 83 страниц)
В С# имеется специальное средство, называемое инициализатором коллекции и упрощающее инициализацию некоторых коллекций. Вместо того чтобы явно вызывать метод Add()
, при создании коллекции можно указать список инициализаторов. После этого компилятор организует автоматические вызовы метода Add()
, используя значения из этого списка. Синтаксис в данном случае ничем не отличается от инициализации массива. Обратимся к следующему примеру, в котором создается коллекция типа List
, инициализируемая символами С, А, Е, В, D и F.
List
После выполнения этого оператора значение свойства lst.Count
будет равно 6, поскольку именно таково число инициализаторов. А после выполнения следующего цикла foreach
:
foreach(ch in lst)
Console.Write(ch + " ");
получится такой результат:
С A E В D F
Для инициализации коллекции типа LinkedList
, в которой хранятся пары «ключ-значение», инициализаторы приходится предоставлять парами, как показано ниже.
SortedListcint, string> lst =
new SortedList
{ {1, «один»}, {2, «два» }, {3, «три»} };
Компилятор передаст каждую группу значений в качестве аргументов методу Add()
. Следовательно, первая пара инициализаторов преобразуется компилятором в вызов Add(1, «один»)
.
Компилятор вызывает метод Add()
автоматически для ввода инициализаторов в коллекцию, и поэтому инициализаторы коллекций можно использовать только в коллекциях, поддерживающих открытую реализацию метода Add()
. Это означает, что инициализаторы коллекций нельзя использовать в коллекциях типа Stack
, Stack
, Queue
или Queue
, поскольку в них метод Add()
не поддерживается. Их нельзя применять также в тех коллекциях типа LinkedList
, где метод Add()
предоставляется как результат явной реализации соответствующего интерфейса.
ГЛАВА 26 Сетевые средства подключения к Интернету
Язык C# предназначен для программирования в современной вычислительной среде, где Интернету, естественно, принадлежит весьма важная роль. Одной из главных целей разработки C# было внедрение в этот язык программирования средств, необходимых для доступа к Интернету. Такой доступ можно было осуществить и в предыдущих версиях языков программирования, включая С и C++, но поддержка операций на стороне сервера, загрузка файлов и получение сетевых ресурсов в этих языках не вполне отвечали потребностям большинства программистов. Эта ситуация коренным образом изменилась в С#. Используя стандартные средства C# и среды .NET Framework, можно довольно легко сделать приложения совместимыми с Интернетом и написать другие виды программ, ориентированных на подключение к Интернету.
Поддержка сетевого подключения осуществляется через несколько пространств имен, определенных в среде .NET Framework, и главным среди них является пространство имен System.Net
. В нем определяется целый ряд высокоуровневых, но простых в использовании классов, поддерживающих различные виды операций, характерных для работы с Интернетом. Для этих целей доступен также ряд пространств, вложенных в пространство имен System.Net
. Например, средства низкоуровневого сетевого управления через сокеты находятся в пространстве имен System.Net.Sockets
, поддержка электронной почты – в пространстве имен System.Net.Mail
, а поддержка защищенных сетевых потоков – в пространстве имен System.Net.Security
. Дополнительные функциональные возможности предоставляются в ряде других вложенных пространств имен. К числу других не менее важных пространств имен, связанных с сетевым подключением к Интернету, относится пространство System.Web
. Это и вложенные в него пространства имен поддерживают сетевые приложения на основе технологии ASP.NET.
В среде .NET Framework имеется достаточно гибких средств и возможностей для сетевого подключения к Интернету. Тем не менее для разработки многих приложений более предпочтительными оказываются функциональные возможности, доступные в пространстве имен System.Net
. Они и удобны, и просты в использовании. Именно поэтому пространству имен System.Net
будет уделено основное внимание в этой главе.
Пространство имен System.Net довольно обширно и состоит из многих членов. Полное их описание и обсуждение всех аспектов программирования для Интернета выходит далеко за рамки этой главы. (На самом деле для подробного рассмотрения всех вопросов, связанных с сетевым подключением к Интернету и его поддержкой в С#, потребуется отдельная книга.) Однако целесообразно хотя бы перечислить члены пространства имен System. Net, чтобы дать какое-то представление о том, что именно доступно для использования в этом пространстве.
Ниже перечислены классы, определенные в пространстве имен System.Net.
AuthenticationManager
Authorization
Cookie
CookieCollection
CookieContainer
CookieException
CredentialCache
Dns
DnsEndPoint
DnsPermission
DnsPermissionAttribute
DownloadDataCompletedEventArgs
DownloadProgressChangedEventArgs
DownloadstringCompletedEventArgs
EndPoint
EndpointPermission
FileWebRequest
FileWebResponse
FtpWebRequest
FtpWebResponse
HttpListener
HttpListenerBasicIdentity
HttpListenerContext
HttpListenerException
HttpListenerPrefixCol lection
HttpListenerRequest
HttpListenerResponse
HttpVersion
HttpWebRequest
HttpWebResponse
IPAddress
IPEndPoint
IPEndPointCollection
IPHostEntry
IrDAEndPoint
NetworkCredential
OpenReadCompletedEventArgs
OpenWriteCompletedEventArgs
ProtocolViolationException
ServicePoint
ServicePointManager
SocketAddress
SocketPermission
SocketPermissionAttribute
TransportContext
UploadDataCompletedEventArgs
UploadFileCompletedEventArgs
UploadProgressChangedEventArgs
UploadstringCompletedEventArgs
UploadValuesCompletedEventArgs
WebClient
WebException
WebHeaderCollection
WebPermission
WebPermissionAttribute
WebProxy
WebRequest
WebRequestMethods
WebRequestMethods.File
WebRequestMethods.Ftp
WebRequestMethods.Http
WebResponse
WebUtility
Кроме того, в пространстве имен System.Net определены перечисленные ниже интерфейсы.
AuthenticationModule
IcertificatePolicy I Credential Pol icy
ICredentials
IcredentialsByHost IWebProxy
IWebProxyScript
IWebRequestCreate
В этом пространстве имен определяются также приведенные ниже перечисления.
AuthenticationSchemes
DecompressionMethods FtpStatusCode
HttpRequestHeader
HttpResponseHeader HttpStatusCode
NetworkAccess
SecurityProtocolType TransportType
WebExceptionStatus
Помимо этого, в пространстве имен System.Net определен ряд делегатов.
Несмотря на то что в пространстве имен System.Net
определено немало членов, лишь немногие из них на самом деле требуются при решении наиболее типичных задач программирования для Интернета. Основу сетевых программных средств составляют абстрактные классы WebRequest
и WebResponse
. От этих классов наследуют все классы, поддерживающие конкретные сетевые протоколы. (Протокол определяет правила передачи данных по сети.) Например, к производным классам, поддерживающим стандартный сетевой протокол HTTP, относятся классы HttpWebRequest
и HttpWebResponse
.
Классы HttpWebRequest
и HttpWebResponse
довольно просты в использовании. Тем не менее решение некоторых задач можно еще больше упростить, применяя подход, основанный на классе WebClient
. Так, если требуется только загрузить или выгрузить файл, то для этой цели лучше всего подойдет класс WebClient
.
В основу программирования для Интернета положено понятие универсального идентификйтора ресурса (URI), иногда еще называемого унифицированным указателем информационного ресурса (URL). Этот идентификатор описывает местоположение ресурса в сети. В корпорации Microsoft принято пользоваться сокращением URI при описании членов пространства имен System.Net
, и поэтому в данной книге выбрано именно это сокращение для обозначения универсального идентификатора ресурса. Идентификаторы URI, без сомнения, известны каждому, кто хотя бы раз пользовался браузером для поиска информации в Интернете. По существу, это адрес информационного ресурса, который указывается в соответствующем поле окна браузера.
Ниже приведена общая форма идентификатора URI:
Протокол: //Идентификационный_номер_сервера/Путь_к_файлу/Запрос
где Протокол — это применяемый протокол, например HTTP; Идентификационный_номер_сервера – конкретный сервер, например mhprofessional.com или HerbSchildt.com; Путь_к_файлу — путь к конкретному файлу. Если же Путь_к_ файлу не указан, то получается страница, доступная на указанном сервере по умолчанию. И наконец, Запрос обозначает информацию, отправляемую на сервер. Указывать Запрос необязательно. В C# идентификаторы URI инкапсулированы в класс Uri
, рассматриваемый далее в этой главе.
В классах, находящихся в пространстве имен System.Net
, поддерживается модель взаимодействия с Интернетом по принципу запроса и ответа. При таком подходе пользовательская программа, являющаяся клиентом, запрашивает информацию у сервера, а затем переходит в состояние ожидания ответа. Например, в качестве запроса программа может отправить на сервер идентификатор URI некоторого веб-сайта. В ответ она получит гипертекстовую страницу, соответствующую указанному идентификатору URL Такой принцип запроса и ответа удобен и прост в применении, поскольку большинство деталей сетевого взаимодействия реализуются автоматически.
На вершине иерархии сетевых классов находятся классы WebRequest
и WebResponse
, реализующие так называемые подключаемые протоколы. Как должно быть известно большинству читателей, для передачи данных в сети применяется несколько разнотипных протоколов. К числу наиболее распространенных в Интернете относятся протокол передачи гипертекстовых файлов (HTTP), а также протокол передачи файлов (FTP). При создании идентификатора URI его префикс обозначает применяемый сетевой протокол. Например, в идентификаторе http://www.HerbSchildt.com используется префикс http, обозначающий протокол передачи гипертекстовых файлов (HTTP).
Как упоминалось выше, классы WebRequest
и WebResponse
являются абстрактными, а следовательно, в них определенны в самом общем виде операции запроса и ответа, типичные для всех протоколов. От этих классов наследуют более конкретные производные классы, в которых реализуются отдельные протоколы. Эти производные классы регистрируются самостоятельно, используя для этой цели статический метод RegisterPrefix()
, определенный в классе WebRequest
. При создании объекта типа WebRequest
автоматически используется протокол, указываемый в префиксе URI, если, конечно, он доступен. Преимущество такого принципа «подключения» протоколов заключается в том, что большая часть кода пользовательской программы остается без изменения независимо от типа применяемого протокола.
В среде выполнения .NET Runtime протоколы HTTP, HTTPS и FTP определяются автоматически. Так, если указать идентификатор URI с префиксом HTTP, то будет автоматически получен HTTP-совместимый класс, который поддерживает протокол HTTP. А если указать идентификатор URI с префиксом FTP, то будет автоматически получен FTP-совместимый класс, поддерживающий протокол FTP.
При сетевом подключении к Интернету чаще всего применяется протокол HTTP, поэтому именно он и рассматривается главным образом в этой главе. (Тем не менее аналогичные приемы распространяются и на все остальные поддерживаемые протоколы.) Протокол HTTP поддерживается в классах HttpWebRequest
и HttpWebResponse
. Эти классы наследуют от классов WebRequest
и WebResponse
, а кроме того, имеют собственные дополнительные члены, применимые непосредственно к протоколу HTTP.
В пространстве имен System.Net
поддерживается как синхронная, так и асинхронная передача данных. В Интернете предпочтение чаще всего отдается синхронным транзакциям, поскольку ими легче пользоваться. При синхронной передаче данных пользовательская программа посылает запрос и затем ожидает ответа от сервера. Но для некоторых разновидностей высокопроизводительных приложений более подходящей оказывается асинхронная передача данных. При таком способе передачи данных пользовательская программа продолжает обработку данных, ожидая ответа на переданный запрос. Но организовать асинхронную передачу данных труднее. Кроме того, не во всех программах можно извлечь выгоды из асинхронной передачи данных. Например, когда требуется получить информацию из Интернета, то зачастую ничего другого не остается, как ожидать ее. В подобных случаях потенциал асинхронной передачи данных используется не полностью. Вследствие того что синхронный доступ к Интернету реализуется проще и намного чаще, именно он и будет рассматриваться в этой главе.
Далее речь пойдет прежде всего о классах WebRequest
и WebResponse
, поскольку именно они положены в основу сетевых программных средств, доступных в пространстве имен System.Net
.
Класс WebRequest
Класс WebRequest
управляет сетевым запросом. Он является абстрактным, поскольку в нем не реализуется конкретный протокол. Тем не менее в нем определяются те методы и свойства, которые являются общими для всех сетевых запросов. В табл. 26.1 сведены методы, определенные в классе WebRequest
и поддерживающие синхронную передачу данных, а в табл. 26.2 – свойства, объявляемые в классе WebRequest
. Устанавливаемые по умолчанию значения свойств задаются в производных классах. Открытые конструкторы в классе WebRequest
не определены.
Для того чтобы отправить запрос по адресу URI, необходимо сначала создать объект класса, производного от класса WebRequest
и реализующего требуемый протокол. С этой целью вызывается статический метод Create()
, определенный в классе WebRequest
. Метод Create()
возвращает объект класса, наследующего от класса WebRequest
и реализующего конкретный протокол.
Таблица 26.1. Методы, определенные в классе WebRequest
Метод – Описание
public static WebRequest Create(string requestUriString) – Создает объект типа WebRequest для идентификатора URI, указываемого в строке requestUriString. Возвращаемый объект реализует протокол, заданный префиксом идентификатора URI. Следовательно, возвращаемый объект будет экземпляром класса, призводного от класса WebRequest. Если затребованный протокол недоступен, то генерируется исключение NotSupportedException. А если недействителен указанный формат идентификатора URI, то генерируется исключение UriFormatException
public static WebRequest Create(Uri requestUri) – Создает объект типа WebRequest для идентификатора URI, указываемого с помощью параметра reques tUri. Возвращаемый объект реализует протокол, заданный префиксом идентификатора URI. Следовательно, возвращаемый объект будет экземпляром класса, призводного от класса WebRequest. Если затребованный протокол недоступен, то генерируется исключение NotSupportedException
public virtual Stream GetRequestStream() – Возвращает поток вывода, связанный с запрошенным ранее идентификатором URI
public virtual WebResponse GetResponse() – Отправляет предварительно сформированный запрос и джидает ответа. Получив ответ, возвращает его в виде объекта класса WebReponse. Этот объект используется затем в программе для получения информации по указанному адресу URI
Таблица 26.2. Свойства, определенные в классе WebRequest
Свойство – Описание
public AuthenticationLevel AuthenticationLevel( get; set; } – Получает или устанавливает уровень аутентификации
public virtual RequestCachePolicy CachePolicy { get; set; } – Получает или устанавливает правила использования кеша, определяющие момент получения ответа из кеша
public virtual string ConnectionGroupName { get; set; } – Получает или устанавливает имя группы подключения. Группы подключения представляют собой способ создания ряда запросов. Они не нужны для простых транзакций в Интернете
public virtual long ContentLength { get; set; } – Получает или устанавливает длину передаваемого содержимого
public virtual string ContentType { get; set; } – Получает или устанавливает описание передаваемого содержимого
public virtual Icredentials Credentials { get; set; } – Получает или устанавливает мандат, т.е. учетные данные пользователя
public static RequestCachePolicy DefaultCachePolicy { get; set; } – Получает или устанавливает правила использования кеша по умолчанию, определяющие момент получения ответа из кеша
public static IWebProxy DefaultWebProxy { get; set; } – Получает или устанавливает используемый поумолчанию прокси-сервер
public virtual WebHeaderCollection Headers{ get; set; } – Получает или устанавливает коллекцию заголовков
public TokenlmpersonationLevel ImpersonationLevel { get; set; } – Получает или устанавливает уровень анонимного воплощения
public virtual string Method { get; set; } – Получает или устанавливает протокол
public virtual bool PreAuthenticate { get; set; } – Если принимает логическое значение true, то в отправляемый запрос включается информация для аутентификации. А если принимает логическое значение false, то информация для аутентификации предоставляется только по требованию адресата URI
public virtual IWebProxy Proxy { get; set; } – Получает или устанавливает прокси-сервер. Применимо только в тех средах, где используется прокси-сервер
public virtual Uri RequestUri { get; } – Получает идентификатор URI конкретного запроса
public virtual int Timeout { get; set; } – Получает или устанавливает количество миллисекунд, в течение которых будет ожидаться ответ на запрос. Для установки бесконечного ожидания используется значение Timeout. Infinite
public virtual bool UseDefaultCredential { get; set; } – Получает или устанавливает значение, которое определяет, используется ли для аутентификации устанавливаемый по умолчанию мандат. Если имеет логическое значение true, то используется устанавливаемый по умолчанию мандат, т.е. учетные данные пользователя, в противном случае этот мандат не используется
Класс WebResponse
В классе WebResponse
инкапсулируется ответ, получаемый по запросу. Этот класс является абстрактным. В наследующих от него классах создаются отдельные его версии, поддерживающие конкретный протокол. Объект класса WebResponse
обычно получается в результате вызова метода GetResponse()
, определенного в классе WebRequest
. Этот объект будет экземпляром отдельного класса, производного от класса WebResponse
и реализующего конкретный протокол. Методы, определенные в классе WebResponse
, сведены в табл. 26.3, а свойства, объявляемые в этом классе, – в табл. 26.4. Значения этих свойств устанавливаются на основании каждого запроса в отдельности. Открытые конструкторы в классе WebResponse
не определяются.
Таблица 26.3. Наиболее часто используемые методы, определенные в классе WebResponse
Метод – Описание
public virtual void Close()
Закрывает ответный поток. Закрывает также поток ввода ответа, возвращаемый методом
GetResponseStream()
public virtual Stream GetResponseStream()
Возвращает поток ввода, связанный с запрашиваемым URI. Из этого потока могут быть введены данные из запрашиваемого URI
Таблица 26.3. Свойства, определенные в классе WebResponse
Свойство – Описание
public virtual long ContentLength { get; set; } – Получает или устанавливает длину принимаемого содержимого. Устанавливается равным -1, если данные о длине содержимого недоступны
public virtual string ContentType { get; set; } – Получает или устанавливает описание принимаемого содержимого
public virtual WebHeaderCollection Headers { get; } – Получает или устанавливает коллекцию заголовков, связанных с URI
public virtual bool IsFromCache { get; } – Принимает логическое значение true, если запрос получен из кэша. А если запрос доставлен по сети, то принимает логическое значение false
public virtual bool IsMutuallyAuthenticated { get; } – Принимает логическое значение true, если клиент и сервер опознают друг друга, а иначе – принимает логическое значение false
public virtual Uri – Получает URI, по которому был сформирован ответ.
ResponseUri { get; } – Этот идентификатор может отличаться от запрашиваемого, если ответ был переадресован по другому URI
Классы HttpWebRequest и HttpWebResponse
Оба класса, HttpWebRequest
и HttpWebResponse
, наследуют от классов WebRequest
и WebResponse
и реализуют протокол HTTP. В ходе этого процесса в обоих классах вводится ряд дополнительных свойств, предоставляющих подробные сведения о транзакции по протоколу HTTP. О некоторых из этих свойств речь пойдет далее в настоящей главе. Но для выполнения простых операций в Интернете эти дополнительные свойства, как правило, не требуются.
Первый простой пример
Доступ к Интернету организуется на основе классов WebRequest
и WebResponse
. Поэтому, прежде чем рассматривать этот процесс более подробно, было бы полезно обратиться к прострму примеру, демонстрирующему порядок доступа к Интернету по принципу запроса и ответа. Глядя на то, как эти классы применяются на практике, легче понять, почему они организованы именно так, а не как-то иначе.
В приведенном ниже примере программы демонстрируется простая, но весьма типичная для Интернета операция получения гипертекстового содержимого из конкретного веб-сайта. В данном случае содержимое получается из веб-сайта издательства McGraw-Hill по адресу www.McGraw-Hill.com, но вместо него можно подставить адрес любого другого веб-сайта. В этой программе гипертекстовое содержимое выводится на экран монитора отдельными порциями по 400 символов, чтобы полученную информацию можно было просматривать, не прибегая к прокрутке экрана.
// Пример доступа к веб-сайту.
using System;
using System.Net;
using System.IO;
class NetDemo {
static void Main() {
int ch;
// Сначала создать объект запроса типа WebRequest по указанному URI.
HttpWebRequest req = (HttpWebRequest)
WebRequest.Create(http://www.McGraw-Hill.com);
// Затем отправить сформированный запрос и получить на него ответ.
HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
// Получить из ответа поток ввода.
Stream istrm = resp.GetResponseStream();
/* А теперь прочитать и отобразить гипертекстовое содержимое, полученное по указанному URI. Это содержимое выводится на экран отдельными порциями по 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();
}
}
Ниже приведена первая часть получаемого результата. (Разумеется, это содержимое может со временем измениться в связи с обновлением запрашиваемого веб-сайта, и поэтому у вас оно может оказаться несколько иным.)
Нажмите клавишу
Итак, выше приведена часть гипертекстового содержимого, полученного из вебсайта издательства McGraw-Hill по адресу www.McGraw-Hill. com. В рассматриваемом здесь примере программы это содержимое просто выводится в исходном виде на экран посимвольно и не форматируется в удобочитаемом виде, как это обычно делается в окне браузера.
Проанализируем данную программу построчно. Прежде всего обратите внимание на использование в ней пространства имен System.Net
. Как пояснялось ранее, в этом пространстве имен находятся классы сетевого подключения к Интернету. Обратите также внимание на то, что в данную программу включено пространство имен System.IO
, которое требуется для того, чтобы прочитать полученную на веб-сайте информацию, используя объект типа Stream
.
В начале программы создается объект типа WebRequest
, содержащий требуемый URL Как видите, для этой цели используется метод 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
.