|
||||||||||||||
|
Глава 22Доступ в Интернет В главах 16–18 было показано, как использовать C# для создания мощных и эффективных динамических страниц Web с помощью ASP.NET, а также служб Web. Клиенты, обращающиеся к страницам ASP.NET, по большей части будут пользователями Internet Explorer или какого-либо другого браузера Web. Но иногда необходимо, чтобы создаваемые приложения действовали как клиенты Web. Это может быть, например, если нужно добавить в создаваемые приложения свойства просмотра Web, или, если необходимо, чтобы создаваемые приложения программным путем получали информацию с некоторых web-сайтов. В последнем случае обычно лучше, чтобы сайт реализовал службу Web, но при обращении к внешним сайтам возможно отсутствие контроля за тем, как реализован сайт, и поэтому может не быть другой возможности выбора, кроме программного доступа к сайту, который реализован как стандартные страницы HTML, ASP или ASP.NET. Именно эту сторону картины мы кратко рассмотрим сейчас. В частности, будут представлены средства базовых классов .NET для использования различных сетевых протоколов, например HTTP для доступа к сетям и Интернету в качестве клиента. Мы обсудим следующие вопросы: □ Запрос данных из Web и получение ответа от серверов □ Отправку данных HTTP POST □ Извлечение информации заголовка HTTP из ответов серверов Коротко коснемся средств, существующих для прямого доступа к службам нижнего уровня, таким как отправка и получение пакетов TCP и ожидание приема на определенных портах. Пространства имен System.Netи System.Net.Socketsсодержат большинство базовых классов .NET, которые связаны с работой в сети с точки зрения клиента. Пространство имен System.Netобычно связано с операциями более высокого уровня, например загрузкой и выгрузкой файлов и выполнением запросов Web с помощью HTTP и других протоколов, в то время как System.Net.Socketsсодержит классы, связанные с операциями более низкого уровня. Они более полезны при работе непосредственно с сокетами или такими протоколами, как TCP/IP, и используются по большей части для сокрытия соответствующей функции API Windows. В этой главе используется достаточно практичный подход: представлен ряд постепенно усложняющихся примеров в сопровождении соответствующей теории и с обсуждением сетевых концепций. Мы начнем с простейшего случая, когда необходимо просто послать серверу запрос и сохранить или обработать полученную информацию. Класс WebClientЕсли необходимо выполнить запрос файла по определенному URL, то, скорее всего, самым простым классом .NET для использования в этом случае окажется System.Net.WebClient. Это класс максимально высокого уровня, созданный для выполнения базовых операций с помощью одной или двух команд. Загрузка файловСуществует два способа загрузки файлов с web-сайта с помощью WebClient, в зависимости от того, хотим ли мы файл сохранить или обработать его содержимое файла непосредственно внутри приложения. Если нужно просто сохранить файл, то вызывается метод DownloadFile(). Этот метод получает два параметра: URL, из которого необходимо извлечь файл, и имя файла (или путь доступа), в котором мы хотим сохранить файл. WebClient Client = new WebClient(); Client.DownloadFile("http://www.Wrox.com/default.htm", "index.htm"); Более часто приложению приходится обрабатывать данные, полученные с web-сайта. Чтобы сделать это, используется метод OpenRead(), который возвращает ссылку типа Stream. Затем можно извлекать данные просто из потока. WebClient Client = new WebClient(); Stream sfrm = Client.OpenRead("http://www.Wrox.com/default.htm"); Пример: базовый клиент WebПервый пример продемонстрирует использование метода webClient.OpenRead(). В этом случае содержимое загруженных данных просто выводится в окне списка. Проект создается как стандартное приложение C# для Windows, в него добавляется окно списка с именем listBox1, в котором выводится содержимое загруженного файла. Затем в конструкторе основной формы делаются изменения: public Form1() { InitializeComponent(); System.Net.WebClient Client = new WebClient(); Stream strm = Client.OpenRead("http://www.wrox.com"); StreamReader sr = new StreamReader(strm); string line; do { line = sr.ReadLine(); listBox1.Items.Add(line); } while (line != null) strm.Close(); } Для упрощения URI в программе жестко закодирован.
Отметим, что в этом примере использованы два потока — StreamReaderи соединенный с ним сетевой поток. Это обычно позволяет получать данные из потока как текст и использовать методы более высокого уровня, такие как ReadLine(), которые доступны в классе StreamReader. Это прекрасный пример сделанного в главе 14 замечания о достоинствах перехода от концепции перемещения данных к концепции потока. Выполнение примера создает следующий результат: Выгрузка файловКласс WebClientобладает также методами UploadFile()и UploadData(). Различие между ними состоит в том, что UploadFile()выгружает указанный файл, заданный именем файла, в то время как UploadData()выгружает двоичные данные, которые поставляются как массив байтов: WebClient client = new WebClient(); client.UploadData("http://www.ourwebsite.com/NewFile.htm", "C:\WebSiteFiles\NewFile.htm"); byte [] image; // код для инициализации изображения, поэтому он содержит все // двоичные данные для некоторого файла jpg client.UploadData("http://www.ourwebsite.com/NewFile.jpg", image); Классы WebRequestКласс WebClientочень просто использовать, но он имеет ограниченные возможности. В частности, нельзя использовать его для предоставления полномочий аутентификации, так как существует не много сайтов, которые будут принимать выгружаемые файлы без аутентификации. Можно добавлять в запросы заголовочную информацию и проверять всю возвращаемую заголовочную информацию, но только в очень общем смысле, потому что нет специальной поддержки для какого-либо протокола. Причина этого состоит в том, что WebClientявляется классом общего назначения, созданным для работы с любым протоколом, для которого можно послать запрос и получить ответ (HTTP, FTP и т. д.). Он не может обрабатывать дополнительные свойства, специфические для какого-то одного протокола, такие как cookies, специфические для HTTP. Если желательно воспользоваться этими свойствами, необходимо выбрать семейство классов на основе двух других классов в пространстве имен System.Net: WebRequestи WebResponse. Начнем с рассмотрения того, как загрузить страницу Web с помощью этих классов — тот же пример, что и раньше, но использующий WebRequestи WebResponse. В процессе изложения мы немного коснемся иерархии вовлеченных классов, а затем покажем, как воспользоваться дополнительными свойствами HTTP, поддерживаемыми этой иерархией. Следующий код доказывает модификации, которые необходимо сделать в примере BasicWebClient, чтобы он использовал классы WebRequestи WebResponse. public Form1() { InitializeComponent(); WebRequest wrq = WebRequest.Create("http://www.wrox.com"); WebResponse wrs = wrq.GetResponse(); Stream strm = wrs.GetResponseStream(); StreamReader sr = new StreamReader(strm); string line; while ((line = sr.ReadLine()) != null) { listBox1.Items.Add(line); } strm.Close(); } Этот код начинается с создания экземпляра объекта, представляющий запрос Web. Необычно то, что это делается не с помощью использования конструктора, а с помощью вызова статического метода WebRequest.Create(); в следующем разделе будет показано, почему так это сделано. Класс WebRequestпредставляет запрос информации, который посылается по определенному URI, и поэтому необходимо передать URI с помощью метода Create(). WebResponseпредставляет данные, присылаемые назад сервером. Вызов метода WebRequest.GetResponse()в действительности посылает запрос серверу Web и создает объект Response, который можно использовать для проверки возвращаемых данных. Как и для объекта WebClient, можно получить поток, представляющий эти данные с помощью метода WebResponse.GetResponseStream(). Другие свойства WebRequest и WebResponseЗдесь кратко будут упомянуты пара других областей, в которых WebRequestи WebResponseи связанные классы предоставляют хорошую поддержку. Информация заголовка HTTP Важной частью протокола HTTP является возможность послать значительную заголовочную информацию с помощью потоков запроса и ответа. Эта информация может включать данные GET и POST, cookies, а также данные определенного пользователя, посылающего запрос. Как и можно было ожидать, предоставляется полная поддержка заданию и доступу к этим данным. Однако эта поддержка не является частью классов WebRequestи WebResponse, она реализована двумя производными классами: HttpWebRequestи HttpWebResponse. Как скоро будет показано, при создании объекта WebRequestс помощью обычного механизма, если предоставленный URI был URI HTTP, то получаемая ссылка в действительности указывает на объект HttpRequest, и можно при желании преобразовать эту ссылку в такой объект. Реализация HttpRequestметода GetResponse()возвращает объект HttpWebResponseчерез ссылку WebResponse, поэтому снова можно выполнить простое преобразование для доступа к свойствам, специфическим для HTTP. Подробное описание этой области представлено в документации MSDN для классов HttpWebRequestи HttpWebResponse. Асинхронные запросы страниц Дополнительным полезным свойством WebRequestвместо WebClientявляется возможность асинхронного запроса страниц. Это важно, так как в Интернете возможна достаточно длительная задержка между отправкой запроса на хост и началом получения каких-либо данных. Методы, подобные WebClient.DownloadDataи WebRequest.GetResponse, не возвращают управление, пока с сервера не вернется ответ. Может оказаться нежелательным, чтобы приложение было связано с ожиданием в течение этого времени. В таком случае попробуйте воспользоваться методами BeginGetResponse()и EndGetResponse(). Они работают асинхронно. Если вызвать BeginGetResponse(), то запрос будет отправлен на хост, а метод немедленно вернет управление, предоставляя делегата типа AsyncCallback. Пока сервер отвечает на запрос, можно будет выполнять другую работу. Подробное описание этих методов можно найти в MSDN. Отображение выходных данных в виде страницы HTMLПервый пример показывает, что базовые классы .NET существенно облегчают загрузку и обработку данных из Интернета. Однако до сих пор файлы выводились только как простой текст. В приложении желательно часто просматривать файл HTML с помощью интерфейса в стиле Internet Explorer, чтобы установить, как действительно выглядит документ Web. К сожалению, когда писалась эта книга, базовые классы .NET не включали никакой собственной поддержки для управления этими свойствами интерфейса в стиле Internet Explorer. Чтобы сделать это, необходимо либо программным путем вызвать Internet Explorer, либо воспользоваться элементом управления ActiveX WebBrowser, который существовал уже до появления .NET.
Программный запуск процесса Internet Explorer, направленного на заданную страницу Web, можно выполнить с помощью класса Processиз пространства имен System.Diagnostics. Process myProcess = new Process(); myProcess.StartInfо.FileName = "iexplore.exe"; myProcess.StartInfo.Arguments = "http://www.wrox.com"; myProcess.Start(); Однако IE при этом запускается и как отдельное окно, которое на самом деле не соединено и не находится под управлением приложения. Следовательно, хотя этот код приведен здесь для справки, такая техника не подходит для частого применения. С другой стороны использование элемента управления WebBrowser означает, что выведенный браузер может составить интегральную часть приложения, и приложение получит полный контроль над работой браузера. Этот элемент управления достаточно развит, обладает большим числом методов свойств и событий. Простейшим способом встроить этот элемент управления с помощью Visual Studio.NET является добавление элемента управления в панель инструментов. Для этого щелкните правой кнопкой мыши на Toolbox в VisualStudio.NET и выберите Customize Toolbox из контекстного меню, что вызывает диалоговое окно, приведенное ниже. Необходимо выбрать вкладку COM Component и щелкнуть на Microsoft Web Browser. Элемент управления WebBrowser появится теперь в панели инструментов, можно щелкнуть та нем, чтобы поместить его на форму в приложении Windows на C#, так же, как любой другой элемент управления Windows Forms в .NET. Visual Studio.NET автоматически создает весь код взаимодействия COM, необходимый программе C# для работы в качестве клиента с этим элементом управления, чтобы можно было интерпретировать его как просто элемент управления .NET. Это будет продемонстрировано с помощью другого очень короткого примера DisplayWebPage, в котором выводится страница Web с жестко закодированным URI. DisplayWebPageсоздается как стандартное приложение Windows C#, элемент управления ActiveX WebBrowserпомещается в форму, как описано выше. По умолчанию Visual Studio.NET именует соответствующую переменную axWebBrowser1, и здесь будет оставлено имя по умолчанию. Затем в конструктор Form1добавляется код: public Form1() // Требуется для поддержки Windows Form Designer. InitializeComponent(); int zero = 0; object oZero = zero; string emptyString = ""; object oEmptyString = emptyString; axWebBrowser1.Navigate("http://www.wrox.com", ref oZero, ref oEmptyString, ref oEmptyString, ref oEmptyString); } В этом коде используется метод Navigate()элемента управления WebBrowser, который реально посылает запрос HTTP и выводит данные заданного URI. Первый параметр этого метода является строкой, содержащей URL, куда будет совершено перемещение. Остальные параметры соответственно позволяют: задать различные флажки; указать именованную рамку, в которой должен быть выведен браузер; определить любые данные POST, посылаемые с запросом, и дополнительную информацию заголовка HTTP. Используемых по умолчанию нулевых значений и пустых строк будет в данном случае достаточно. Эти параметры задаются в элементе управления как необязательные, но C# не поддерживает необязательные параметры, поэтому нужно определить их явно. Необходимо также явно объявить объектные ссылки для этих переменных, так как они передаются только по ссылке. Вызов метода Navigate()с параметрами, как показано выше, имеет в принципе тот же результат, как и ввод URL в Internet Explorer для перехода к странице Web. Это единственный код, который необходимо добавить в проект DisplayWebPageвручную. При выполнении этого примера будет получен следующий результат (Visual Studio.NET также использовалась для изменения текста заголовка основной формы). Отметим, что вывод страницы Web таким образом требует только унаследованного элемента управления WebBrowser, не нужно использовать никакие классы из пространства имен System.Net. Иерархия классов WebRequest и WebResponseВ этом разделе более подробно рассматривается архитектура классов WebRequestи WebResponse. Иерархия наследования вовлеченных классов показана на диаграмме. Диаграмма показывает, что иерархия содержит более двух классов, которые используются в коде. Фактически оба класса WebRequestи WebResponseявляются абстрактными, и поэтому нельзя создать экземпляры этих классов. Они существуют как базовые классы для предоставления общей функциональности для работы с запросами и ответами Web независимо от протокола, используемого в данной операции. Любой такой запрос всегда делается с помощью определенного протокола (HTTP, Telnet, FTP, SMTP и т. д.) и выполняется с помощью производного класса для этого протокола. В предыдущем коде, хотя ссылочные переменные были определены как ссылки на базовый класс, метод WebRequest.Create()в действительности давал объект HttpWebRequest, а метод GetResponse()возвращал объект HttpWebResponse тоже в действительности. Почему же этого не видно в коде явно? Ответ заключается в том, что компания Microsoft предоставила механизм на основе фабрики для сокрытия деталей иерархии классов от клиентского кода. Тот факт, что требуется объект, который может иметь дело с протоколом HTTP, очевиден из URI, подставляющего в WebRequest.Create(): http://www.wrox.com. WebRequest.Create()проверяет в URI спецификатор протокола и использует это для создания экземпляра и возврата объекта соответствующего класса. Цель состоит в том, чтобы никогда не использовать конструктор для создания экземпляра объекта WebRequest; таким образом появляется в некоторой степени свобода от необходимости что-либо знать о производных классах. Следует заметить, что теория немного отказывает, если нужно использовать какие-то специальные свойства используемого протокола, которые реализованы как методы производного класса, и в этом случае необходимо выполнить преобразование типа ссылки WebRequestили WebResponseв производный класс. Теоретически с помощью этой архитектуры можно обрабатывать отправку запросов с помощью любого из распространенных протоколов. Однако компания Microsoft в действительности написала производные классы, охватывающие протоколы HTTP и file://. Если желательно иметь дело с другими протоколами, например, FTP, Telnet или SMTP, то нужно либо воспользоваться API Windows и написать свои собственные классы (которые будут внутренне реализованы с помощью Windows API), или ждать, пока независимые поставщики программного обеспечения напишут подходящие классы .NET. Служебные классыВ этом разделе будет представлена пара служебных классов, которые могут облегчить программирование Web при работе с двумя распространенными темами Интернета — URI и адреса IP. URIUriи UriBuilderявляются двумя классами в пространстве имен System(подчеркнем, что не System.Net) и оба предназначены для представления Uri. Различие между ними состоит в том, что UriBuilderсоздает URI по заданным строкам для его компонентов, в то время как Uriвыполняет синтаксический разбор всего URI. Поскольку класс Uriпредназначен скорее для разбиения, а не для создания Uri, он требует полной строки URI, чтобы ее создать. Uri MSPage = new Uri("http://www.Microsoft.com/SomeFolder/SomeFile.htm?Order=- true"); Класс представляет большое число свойств, которые предназначены только для чтения. В объекте Uriне предусмотрены изменения после того, как он был создан. string Query = MSPage.Query; // Order = true string AbsolutePath = MSPage.AbsolutePath; // SomeFolder/SomeFile.htm string Schema = MSPage.Schema; // http int Port = MSPage.Port; // 80 (по умолчанию для http) string AbsolutePath = MSPage.AbsolutePath; // SomeFolder/SomeFile.htm string Host = MSPage.Host; // www.Microsoft.com bool IsDefaultPort = MSPage.IsDefaultPort; // true, так как // 80 — значение по умолчанию UriBuilder, с другой стороны, реализует меньше свойств: лишь столько, чтобы построить полный URI. Однако эти свойства предназначены для чтения-записи. Можно задать компоненты для создания URI с помощью конструктора: Uri MSPage = new UriBuilder("http", "www.Microsoft.com", 80, "SomeFolder/SomeFile.htm", "Order=true"); Или присвоить значения свойствам. UriBuilder MSPage = new UriBuilder(); MSPage.Schema = "http"; MSPage.Host = "www.Microsoft.com"; MSPage.Port = 80; MSPage.Path = "SomeFolder/SomeFile.htm"; MSPage.Query = "Order=true"; После завершения инициализации UriBuilderполучается соответствующий объект Uriсо свойством Uri. Uri CompletedUri = MSPage.Uri; Пример вывода страницыМы проиллюстрируем использование UriBuilderвместе с созданием процесса Internet Explorer на примере DisplayPage. Этот пример позволяет пользователю ввести компоненты URL. Отметим, что имеется в виду URL, а не URI, так как предполагается, что это запрос HTTP. Пользователь сможет затем щелкнуть на кнопке ViewPage, и приложение выведет весь URL в текстовом поле, а также страницу с помощью элемента управления ActiveX WebBrowser. Этот пример, будучи стандартным приложением Windows на C#, выглядит так: Текстовые поля названы соответственно textBoxServer, textBoxPath, textBoxPortи textBoxURI. Добавленный код примера полностью находится в обработчике событий кнопки ViewPage: private void OnClickViewPage(object sender, System.EventArgs e) { UriBuilder Address = new UriBuilder(); Address.Host = textBoxServer.Text; Address.Port = int.Parse(textBoxPort.Text); Address.Scheme = Uri.UriSchemeHttp; Address.Path = textBoxFile.Text; Uri AddressUri = Address.Uri; Process myProcess = new Process(); myProcess.StartInfo.FileName = "iexplorer.exe"; textBoxURI.Text = AddressUri.ToString(); myProcess.StartInfo.Arguments = AddressUri.ToString(); myProcess.Start(); } Адреса IP и имена DNSСерверы в Интернете, так же, как и клиенты, идентифицируются адресами IP или по именам хостов (называемых также именами DNS). Обычно имя хоста, такое как www.wrox.comили www.microsoft.com, является понятным для пользователя и вводится в окне браузера Web. Адрес IP, с другой стороны, является идентификатором, который компьютеры используют для идентификации друг друга, и реально используется для обеспечения того, чтобы запросы и ответы Web направлялись на соответствующие машины. Адрес IP является просто 32-битовым целым числом, которое обычно представляют в так называемом десятичном формате с точками как набор из четырех чисел — каждое между 0 и 255. Компьютер может иметь даже более одного адреса IP. Например, IP 100.100.100.31 при общении с другими компьютерами в Интернете через модем и адрес 10.0.0.1 при общении через свою сетевую карту с другими компьютерами в локальной сети. Следовательно, если другие компьютеры в локальной сети хотят послать сообщение этому компьютеру, они должны обращаться по адресу 10.0.0.1, в то время как компьютеры в Интернете должны обращаться к нему по адресу 100.100.100.31. Адреса обычно динамически присваиваются компьютеру каждый раз либо при загрузке (для компьютеров с постоянным соединением с интранет), либо при установлении связи (для компьютеров, соединенных с провайдером Интернета через модем или аналогичное устройство). Динамически присваиваемые адреса IP передаются компьютеру по мере необходимости из пула адресов, поддерживаемых его провайдером Интернета. Люди редко вводят адреса IP непосредственно, а используют более понятные имена DNS, такие как www.wrox.com. Поэтому необходимо при отправке сетевого запроса сначала транслировать имя DNS в адрес IP, что выполняет один из нескольких серверов DNS. Это организовано следующим образом: некая машина, соединенная с локальным компьютером (что означает либо выделенную машину в локальной сети, либо при модемном соединении машину в корпоративной сети, с которой происходит соединение), будет определена сервером DNS. Эта машина хранит огромную таблицу, отображающую имена DNS в адреса IP для всех известных ему компьютеров, и также содержит адреса IP других серверов DNS, имеющие возможность найти адреса, о которых она не знает. Каждый сетевой компьютер должен знать адрес IP по крайней мере одного локального сервера DNS (это один из элементов данных, которые необходимо предоставить при настройке сетевой конфигурации на компьютере). Когда посылается запрос, компьютер сначала запрашивает сервер DNS, чтобы он сообщил адрес IP, соответствующий введенному адресу домена. Затем, с помощью правильного адреса IP, направляется запрос. Обычно это происходит неявно и поэтому прозрачно, например при перемещении в Интернете. Классы .NET для адресов IP.NET предоставляет ряд классов, которые могут помочь в процессе поиска адресов IP и при получении информации о компьютерах-хостах. IPAddressКласс IPAddressпредставляет адрес IP, который доступен как свойство Addressи может быть преобразован в десятичный формат с точками с помощью ToString(). IPAddressреализует также статический метод Parse(), эффективно выполняя обратное преобразование в ToString()— из десятичной строки с точками в (целочисленный) адрес IP. IPAddress ipAddress = IPAddress.Parse("234.56.78.9"); int address = ipAddress.Address; // address будет присвоено 37105130 string ipString = ipAddress.ToString(); // ipString будет присвоен // текст "234.45.54.2" IPAddressпредоставляет также ряд константных статических полей, которые возвращают известные специальные адреса IP, имеющие специальные значения. //следующая строка задает обратную петлю как "127.0.0.1" // адрес обратной петли указывает локальный хост string loopback = IPAddress.Loopback.ToString(); // следующая строка задает адрес широковещания как "255.255.255.255" // адрес широковещания используется для отправки сообщения // всем машинам в локальной сети String broadcast = IPAddress.Broadcast.ToString();IPHostEntry Класс IPHostEntryинкапсулирует информацию, связанную с определенным хостом (компьютером). Он делает доступным имя хоста с помощью свойства HostName(которое возвращает строку) и все адреса IP с помощью свойства AddressList, которое возвращает массив объектов IPAddress. Класс IPHostEntryбудет показан в действии в примере DNSResolverниже. DNS Класс DNSявляется классом, который может общаться с используемым по умолчанию сервером DNS, чтобы извлечь адреса IP. Двумя важными (статическими) методами здесь являются Resolve(), использующий сервер DNS для получения данных хоста с заданным именем хоста, и GetHostByAddress(), который также посылает назад эти данные, но в этот раз с помощью адреса. Оба метода возвращают объект IPHostEntry. HostEntry wroxHost = Dns.Resolve("www.microsoft.com"); HostEntry wroxHostCopy = Dns.GetHostByAddress("234.234.234.234"); В этом коде оба объекта HostEntryбудут содержать данные серверов Microsoft.com. Класс Dnsотличается от классов IPAddressи IPHostEntryтем, что инкапсулирует возможность реально общаться с серверами для получения информации. Классы IPAddressи IPHostEntry, напротив, мало чем отличаются от структур данных, которые имеют подходящие свойства, позволяющие получить доступ к содержащимся в них данным. Пример: DnsLookupСвязанные с DNS и IP классы будут проиллюстрированы с помощью примера, который ищет имена DNS. Этот снимок экрана показывает DnsLookupв действии. Пример просто предлагает пользователю ввести имя DNS в основное текстовое поле. Когда пользователь нажимает кнопку Resolve, пример использует метод Dns.Resolve()для извлечения ссылки IPHostEntryи выводит имя хоста и адреса IP. Отметим, что выведенное имя хоста может в некоторых случаях отличаться от введенного имени. Это происходит, если одно имя DNS ( www.microsoft.com) действует просто как прокси для другого имени DNS ( www.microsoft.akadns.net). Приложение DnsLookupявляется стандартным оконным приложением C# с элементами управления, как показано на снимке экрана, и присвоенными им соответственно именами textBoxInput, buttonResolve, textBoxHostNameи listboxIPs. Затем в класс Form1добавляется следующий метод заданием его в окне свойств Visual Studio.NET в качестве обработчика событий для нажатия кнопки buttonResolve. void OnResolve(object sender, EventArgs e) { try { IPHostEntry iphost = Dns.Resolve(textBoxInput.Text); foreach(IPAddress ip in iphost.AddressList) { int ipaddress = ip.Address; listBoxIPs.Items.Add(ipaddress); listBoxIPs.Items.Add(" " + Dns.IpToString(ipaddress)); } textBoxHostName.Text = iphost.HostName; } catch(Exception ex) { MessageBox.Show("Unable to process the request because " + "the following problem occurred:\n" + ex.Message, "Exception occurred"); } } Отметим, что в этом коде перехватываются все исключения — исключение может легко возникать, если пользователь вводит что-то, что не является именем DNS, или если сеть выключена. После извлечения экземпляра IPHostEntryиспользуется свойство AddressListдля получения массива, содержащего адреса IP, которые затем перечисляются в цикле foreach. Каждый адрес выводится как целое число и как строка использованием статического метода Dns.IpToString(), который делает то же самое, что и экземпляр метода IPAddress.ToString(). Протоколы нижнего уровняВ этом разделе кратко упоминаются некоторые из классов .NET, используемые для коммуникации на нижнем уровне. Коммуникация между компьютерами работает на нескольких различных уровнях. Рассмотренные до сих пор в этой главе классы действуют на самом высоком уровне, на котором определены особые команды. Наверное, проще всего понять это, рассматривая FTP, так как многие разработчики знакомы с командами FTP. Хотя в последние годы появился ряд хороших утилит FTP на основе UI, но до недавних пор основным инструментом, используемым для FTP в среде Windows, была команда DOS ftp, которая работала в командной строке, и поэтому использование ее включало явный ввод посылаемых серверу инструкций ftp. HTTP, Telnet, SMTP, POP и другие протоколы основываются на похожих наборах команд. Единственное различие состоит в том, что для большинства из этих протоколов используются инструменты, которые скрывают передачу команд от пользователя, так что он обычно об этом не знает. Например, когда в браузере Web вводится URL и посылается запрос Web, браузер на самом деле посылает на сервер команду GET (обычным текстом), соответствующую по своему назначению команде FTP get. Он может также послать команду POST, которая указывает, что к запросу присоединены другие данные. Однако эти протоколы сами по себе не являются достаточными для обеспечения коммуникации между компьютерами. Даже если клиент и сервер понимают, например, протокол HTTP, они все равно не смогут понять друг друга, если не будет точно согласовано, как передавать символы. Какой двоичный формат будет использоваться, и, даже спускаясь на самый нижний уровень, какое напряжение будет использоваться для представления 0 и 1 в двоичных данных? Это связано с тем, что существует множество различных согласуемых протоколом элементов, которые разработчики и инженеры, работающие в этой области, часто называют стеком протоколов. Стек протоколов является, по сути, списком различных протоколов от самого верхнего уровня (HTTP, FTP и т. д.) до базовых протоколов напряжения нижнего уровня и т.д. К счастью, для большей части разработок нет необходимости спускаться так далеко вниз по стеку. Но если требуется эффективная коммуникация, нет ничего необычного в написании кода, который работает непосредственно на уровне пересылки между компьютерами пакетов двоичных данных. Это область таких протоколов, как TCP, и Microsoft предоставляет ряд классов, которые позволяют удобно работать с двоичными данными на этом уровне. Используя эти классы, можно, например, послать широковещательное сообщение, которое будет одновременно получено рядом компьютеров в сети. Классы нижнего уровняСоответствующие классы определены в пространстве имен System.Net.Socketsи позволяют, например, посылать непосредственно запросы TCP или ожидать запросы TCP на определенном порте. Основными классами нижнего уровня являются:
ЗаключениеВ этой главе очень кратко были рассмотрены некоторые из базовых классов .NET, которые имеют дело с открытием клиентских соединений в сети и Интернете, а также отправкой запросов и получением ответов от серверов. Наиболее очевидным результатом этого будет получение страниц HTML. Классы .NET во время написания этой книги по общему признанию слабо охватывали своей поддержкой многие распространенные протоколы, и примечательно, что даже для выполнения такой базовой задачи, как вывод страницы HTML пришлось обращаться к унаследованному элементу управления ActiveX WebBrowser. (Необходимо сказать, что это не является таким уж большим недостатком, поскольку возможность взаимодействия .NET COM и Visual Studio.NET делают использование подобных элементов управления почти таким же простым, как использование собственных элементов управления Windows Forms). Тем не менее доступные классы .NET делают выполнение некоторых важных задач простыми по своей сути, это особенно справедливо для процесса помещения страницы Web в поток или файл. |
|
||||||||||||
Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх | ||||||||||||||
|