Иллюстрированный самоучитель по VB.NET

Сетевые потоки


Сетевые потоки

Среди областей, в которых особенно наглядно проявляются возможности абстрактной модели потока, особое место занимает пересылка информации в Интернете. Работа с низкоуровневым кодом HTML и XML почти не требует усилий со стороны программиста. Хотя в этом разделе мы сможем дать лишь общее представление об этой важной теме и о задействованных пространствах имен, по крайней мере вы увидите, как потоковая интерпретация сетевых данных реализуется на практике. В рассмотренном ниже примере мы передаем информацию на web-сайт и получаем непосредственный HTML-код новой страницы в качестве результата запроса. Анализ полученного HTML-кода приносит нужную информацию.

Мы не смогли устоять перед искушением: наше маленькое приложение обращается на сайт Amazon.com и возвращает текущие сведения о количестве проданных экземпляров нашей книги. Обобщенный алгоритм выглядит следующим образом:

  • Создать объект URI (Universal Resource Locator) передачей строкового параметра конструктору класса URI.

  • Передать объект URI методу Create класса HttpWebRequest, чтобы инициировать выдачу запроса HTTP.

  • Вызвать метод GetResponse класса HttpWebRequest и получить поток.

  • Проанализировать полученный поток, содержащий HTML-код, и извлечь из него нужную информацию, для чего необходимо знать структуру страницы. Кстати, это одна из причин, по которым для получения данных удобнее использовать web-службы: если Amazon неожиданно сменит структуру своих страниц, наше приложение перестанет работать.

    В данном случае страница генерируется следующей строкой запроса, которая и будет использована для создания объекта URI (в конце строки приведен номер ISBN нашей книги):

    http://www.amazon.com/exec/obidos/ASIN/1893115992

    Следующий конструктор создает экземпляр класса с номером ISBN, переданным в виде строкового параметра:

    Public Sub New(ByVal ISBN As String)



    m_URL ="http://wvM.amazon.com/exec/obidos/ASIN/" & ISBN

    End Sub

    Доступное только для чтения свойство GetRank нашего класса просто вызывает закрытую функцию, основной код которой приведен в следующих восьми строках:



    1 Dim theURL As New URI(m_URL)

    2 Dim theRequest As WebRequest

    3 theRequest = WebRequest.Create(theURL)

    4 Dim theResponse As WebResponse

    5 theResponse = theRequest.GetResponse

    6 Dim aReader As New StreamReader(theResponse.GetResponseStream())

    7 Dim theData As String .

    8 theData = aReader.ReadToEnd

    В строке 1 создается объект класса URI. В строках 2 и 3 генерируется web-запрос, передаваемый на сайт Amazon.com. Строки 4 и 5 принимают ответ на запрос, а в строке 6 метод GetResponseStream класса Response конструирует объект StreamReader для полученного потока. На этой стадии строковая переменная theData содержит низкоуровневый HTML-код web-страницы нашей книги.

    <font face=verdana.arial.helvetica size=-l>

    <b>Amazon.com Sales Rank:</b>

    5.776

    </font><br>

    Остается лишь проанализировать переменную theData и извлечь из нее данные о продажах. Для этого мы воспользуемся вспомогательной функцией Analyze:

    Private Function Analyze(ByVal theData As String)As Integer

    Dim Location As Integer

    Location - theData.IndexOf("<b>Amazon.com Sales Rank:</b>")

    + "<b>Amazon.com Sales Rank:</b>".Length

    Dim temp As String

    Do Until theData.Substring(Location.l) = "<" temp = temp

    StheData.Substring(Location.l)

    Location += 1

    Loop

    Return CInt(temp)

    End Function

    Для анализа строковой переменной также можно воспользоваться классом регулярных выражений из пространства имен System.Text.

    Ниже приведен полный код тестового модуля (разумеется, для тестирования вам также понадобится Интернет-соединение):

    Option Strict On Imports System.IO Imports System.Net

    Module Module1

    Sub Main()

    Dim myBook As New AmazonRanker("1893115992")

    MsgBox("This book's current rank is " & myBook.GetRank)

    End Sub

    End Module

    Public Class AmazonRanker

    Private m_URL As String

    Private m_Rank As Integer

    Public Sub New(ByVal ISBN As String)

    m_URL = "http://www.amazon.com/exec/obidos/ASIN/" & ISBN



    End Sub

    Public Readonly

    Property GetRank() As Integer

    Get Return ScrapeAmazon()

    End Get End Property

    Private Function ScrapeAmazon() As Integer Try

    Dim theURL As New URI(m_URL)

    Dim theRequest As WebRequest

    theRequest = WebRequest.Create(theURL)

    Dim theResponse As WebResponse

    theResponse = theRequest.GetResponse

    DimaReaderAsNew

    StreamReader(theResponse.GetResponseStream())

    Dim theData As String

    theData = aReader.ReadToEnd

    Return Analyze(theData) Catch E As Exception

    Console.WriteLine(E.StackTrace)

    Console. ReadLine()

    End Try

    End Function

    Private Function Analyze( ByVal theData As String) As Integer

    Dim Location As Integer

    Location = theData.IndexOf("<b>Amazon.com Sales Rank:</b>") + "<b>Amazon.com

    Sales Rank:</b>".Length Dim temp As String

    Do Until theData.Substring(Location.l) = "<" temp - temp

    &theData.Substring(Location,l) Location += 1 Loop

    Return CInt(temp)

    End Function

    End Class

    Пример этой программы наглядно показывает, какие неуловимые проблемы порой возникают в результате локализации. Когда наш друг запустил эту программу в Европе, она отказалась работать. Оказалось, что на сайте Amazon по вполне понятным причинам используется американский числовой формат, а программа запускалась в европейской версии Windows, в результате чего символ «,» интерпретировался неверно. Разумеется, проблема легко решается — достаточно, чтобы функция возвращала значение строкового типа.




    Содержание раздела