|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Мережеві
потоки
Серед областей, в яких особливо наочно виявляються можливості
абстрактної моделі потоку, особливе місце займає пересилка інформації в Інтернеті.
Робота з низькорівневим кодом HTML і XML майже не вимагає зусиль з боку програміста.
Хоча в цьому розділі ми зможемо дати лише загальне уявлення про цю важливу тему
і про задіяні простори імен, принаймні ви побачите, як потокова
інтерпретація мережевих даних реалізується на практиці. У розглянутому нижче прикладі ми
передаємо інформацію на web-сайт і отримуємо безпосередній HTML-код нової сторінки
як результат запиту. Аналіз отриманої HTML-кода приносить потрібну інформацію. Ми не змогли
встояти перед спокусою: наше маленьке застосування звертається на сайт Amazon.com
і повертає поточні відомості про кількість проданих екземплярів нашої книги.
Узагальнений алгоритм виглядає таким чином:
В даному
випадку сторінка генерується наступним рядком запиту, який і буде використаний
для створення об'єкту 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 Нижче приведений
повний код тестового модуля (зрозуміло, для тестування вам також знадобиться
Інтернет-з'єднання): 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
До принципових
нововведень, відрізняючих VB .NET від попередніх версій VB, відноситься і можливість
зробити на сервері те, що в VB давно робилося для клієнтів. Мова йде про інкапсуляції
загальної функціональності в елементах і багатократному використанні коди. На завершення
цього розділу ми покажемо, як використовувати клас Filesystemmonitor для написання
програми, яка відстежує зміни в заданому каталозі і сигналізує
про них за допомогою подій. Програма
може стежити за каталогом або набором файлів, відповідних заданому фільтру.
Елемент Fil esystemmoni tor навіть може провести рекурсивний перебір
всіх підкаталогів заданого каталога. Події, що ініціюються, перераховані
в таблиці. 9.13. Таблиця
9.13.
Події монітора файлової системи
Втім,
компонент Filesystemmonitor не всесильний — зокрема, він не дозволяє відстежувати зміни
в самому каталозі. Якщо хтось перейменує файл, що знаходиться в каталозі,
ви про це дізнаєтеся, проте перейменування самого каталога залишиться непоміченим
(звичайно, для відстежування подібних змін можна додатково стежити за
батьківським каталогом). Компонент
Fi1esystemmoni tor, як і всі компоненти різних панелей елементів VS .NET, є
конкретною реалізацією більш загального класу. В даному випадку це клас Filesystemwatcher,
похідний від класу Component. Режим відстежування підкаталогів включається
наступною командою: Filesystemwatcherl.IncludeSubdirectohes
= True На мал. 9.6
зображений зразковий вид форми. Компонент Filesystemwatcher знаходиться на вкладці
Components. Візуального інтерфейсу він не має і тому при розміщенні на формі
він відображається на службовій панелі, показаній в нижній частині мал. 9.6. Монітор активізується
наступною нескладною процедурою: Private Sub btnstart_click(Byval sender As System.Object,_ Byval e As System.EventArgs)Handles btnstart.Click If Checkpath()Then Filesystemwatcherl.Path = txtdirectory.Text Filesystemwatcherl.IncludeSubdirectories = chkrecursive.Checked Filesystemwatcherl.EnableRaisingEvents = True End If End Sub Для більшої
надійності ми переконуємося в тому, що заданий каталог існує. При перевірці
використовується клас Directory, тому програма повинна імпортувати простір
імен System. 10: Function Checkpath()As
Boolean If Directory.Exists(txtdirectory.Text)
Then Return (True)
Else txtdirectory.Text=
"" txtdirectory.Focus 0 Msgbox("No
directory by that name exists!") Return False End If End Function
Мал.
9.6. Приклад
використання компоненту Filesystemwatcher VB .NET автоматично
підключає обробник події. У наступному фрагменті при змінах в заданому
каталозі викликається вікно повідомлення: Private Sub
Filesystemwatcherl_changed(Byval sender As Object. Byval e As System.IO.FileSystemEventArgs)
Handles Filesystemwatcher1.Changed Msgbox(txtdirectory.Text & "has changed!") End Sub На жаль,
ми не зможемо повністю описати цей чудовий компонент. Але перш, ніж
ви перейдете до самостійних досліджень, візьміть до відома пару корисних
рад:
Якщо вам
буде потрібно точніший контроль, звернетеся до опису властивості Notifyfilter
в електронній документації. Його значення задається у вигляді констант перераховуваного
типу, об'єднаних оператором Ог, і визначає типи отслежі- ваємих змінах.
Наприклад, можна відстежувати зміни атрибутів, імені і розміру файлу.
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||