|
VB .NET Service Point Program Example
Create a new class library project and you might want to use ServicePointVB as the project and solution names.
|
Rename the source file to ServicePointClassSample to reflect the application that we are going to develop. The default given class name will be automatically renamed to the same name.
Add/edit the code. We have two classes that include the Main() subroutine.
Imports System Imports System.Net Imports System.Collections Imports System.Threading Imports System.IO
' <summary> ' Maintains context information for each HTTP request ' </summary> Public Class HttpState Public httpRequest As HttpWebRequest Public httpResponse As HttpWebResponse Public httpResponseStream As Stream Public uriResource As Uri Public readBuffer() As Byte Public doneEvent As ManualResetEvent Public bytesReceived As Integer
Public Const DefaultReadBufferLength As Integer = 4096
' <summary> ' Constructor for initializing HttpState object ' </summary> ' <param name="resource">URI to retrieve</param> ' <param name="done">Event to signal when done</param> Public Sub New(ByVal resource As Uri, ByVal done As ManualResetEvent) httpRequest = Nothing httpResponse = Nothing uriResource = resource ReDim readBuffer(DefaultReadBufferLength) doneEvent = done bytesReceived = 0 End Sub End Class
' <summary> ' Contains the ServicePoint sample ' </summary> Public Class ServicePointClassSample ' <summary> ' Displays usage information ' </summary> Shared Sub usage() Console.WriteLine("Executable_file_name [-u URI] [-p proxy] [-l count] [-s count]") Console.WriteLine("Available options:") Console.WriteLine(" -u URI URI resource to retrieve") Console.WriteLine(" -p proxy Proxy server to use") Console.WriteLine(" -l count Maximum number of concurrent connections") Console.WriteLine(" -s count Maximum number of ServicePoint instances") Console.WriteLine() End Sub
' <summary> ' Asynchronous delegate for read operation on the HTTP stream. ' </summary> ' <param name="ar">Asynchronous context information for operation</param> Shared Sub HttpStreamReadCallback(ByVal ar As IAsyncResult) Dim httpInfo As HttpState = CType(ar.AsyncState, HttpState)
Try Dim percent As Long Dim count As Integer = httpInfo.httpResponseStream.EndRead(ar)
httpInfo.bytesReceived += count percent = (httpInfo.bytesReceived * 100) / httpInfo.httpResponse.ContentLength Console.WriteLine("{0}: read {1} bytes: {2}%", httpInfo.uriResource.AbsoluteUri.ToString(), count, percent)
If (count > 0) Then PostStreamRead(httpInfo) Else httpInfo.httpResponseStream.Close() httpInfo.httpResponseStream = Nothing httpInfo.httpResponse.Close() httpInfo.httpResponse = Nothing httpInfo.doneEvent.Set() End If Catch ex As Exception Console.WriteLine("Exception occurred: {0}", ex.Message) If (Not IsNothing(httpInfo.httpResponseStream)) Then httpInfo.httpResponseStream.Close() End If If (Not IsNothing(httpInfo.httpResponse)) Then httpInfo.httpResponse.Close() End If httpInfo.doneEvent.Set() End Try End Sub
' <summary> ' Post as an asynchronous receive operation on the HTTP stream. ' </summary> ' <param name="httpInfo">Context information for HTTP request</param> Shared Sub PostStreamRead(ByVal httpInfo As HttpState) Dim asyncStreamRead As IAsyncResult = httpInfo.httpResponseStream.BeginRead( _ httpInfo.readBuffer, _ 0, _ httpInfo.readBuffer.Length, _ New AsyncCallback(AddressOf HttpStreamReadCallback), _ httpInfo _ ) End Sub
' <summary> ' Asynchronous delegate for the HTTP response. ' </summary> ' <param name="ar">Asynchronous context information</param> Shared Sub HttpResponseCallback(ByVal ar As IAsyncResult) Dim httpInfo As HttpState = CType(ar.AsyncState, HttpState)
Try httpInfo.httpResponse = CType(httpInfo.httpRequest.EndGetResponse(ar), HttpWebResponse) httpInfo.httpResponseStream = httpInfo.httpResponse.GetResponseStream() PostStreamRead(httpInfo) Catch wex As WebException Console.WriteLine("Exception occurred: {0}", wex.Message) Console.WriteLine(wex.StackTrace) httpInfo.doneEvent.Set() End Try End Sub
' <summary> ' Retrieves the given resource ' </summary> ' <param name="uriResource">URI to retrieve</param> ' <param name="doneEvent">Event to signal when done</param> Shared Sub GetUriResource(ByVal uriResource As Uri, ByVal doneEvent As ManualResetEvent) Dim httpInfo As HttpState = New HttpState(uriResource, doneEvent)
Try Console.WriteLine("Issuing an async GET request for: {0}", uriResource.ToString()) httpInfo.httpRequest = CType(WebRequest.Create(uriResource.AbsoluteUri), HttpWebRequest) httpInfo.httpRequest.BeginGetResponse(New AsyncCallback(AddressOf HttpResponseCallback), httpInfo) Console.WriteLine("Already POSTED!") Catch wex As WebException Console.WriteLine("GetUriResource() exception occurred: {0}", wex.Message) doneEvent.Set() End Try End Sub
' <summary> ' Main application which parses the command line and issues the HTTP request. ' </summary> ' <param name="args">Command line arguments</param> Shared Sub Main() Dim uriList As ArrayList = New ArrayList() Dim httpProxy As IWebProxy = WebRequest.DefaultWebProxy Dim connectionLimit As Integer = 2 Dim servicePointLimit As Integer = 1 Dim i As Integer
' Parse the command line Dim args As String() = Environment.GetCommandLineArgs()
usage()
For i = 1 To args.GetUpperBound(0) Try Dim CurArg() As Char = args(i).ToCharArray(0, args(i).Length) If (CurArg(0) = "-") Or (CurArg(0) = "/") Then Select Case Char.ToLower(CurArg(1), System.Globalization.CultureInfo.CurrentCulture) Case "u" ' URI to download (get) i = i + 1 uriList.Add(New Uri(args(i))) Exit Select Case "p" ' Name of proxy server to use i = i + 1 httpProxy = New WebProxy(args(i)) Exit Select Case "l" ' Number of connections limited to service point manager i = i + 1 connectionLimit = System.Convert.ToInt32(args(i)) Exit Select Case "s" ' Service point limit i = i + 1 servicePointLimit = System.Convert.ToInt32(args(i)) Exit Select Case Else usage() Exit Sub End Select End If Catch e As Exception usage() Exit Sub End Try Next
Try Dim requestEvents(uriList.Count) As ManualResetEvent
' Setup the ServicePointManager first Console.WriteLine("Setting up the ServicePointManager...") WebRequest.DefaultWebProxy = httpProxy ServicePointManager.MaxServicePoints = servicePointLimit ServicePointManager.DefaultConnectionLimit = connectionLimit ServicePointManager.MaxServicePointIdleTime = 30000 ' 30 seconds Console.WriteLine("Uri count: {0}", uriList.Count)
For i = 0 To uriList.Count - 1 Console.WriteLine("Uri: {0}", (CType(uriList(i), Uri)).ToString())
Dim baseUri As String = "http://" + (CType(uriList(i), Uri)).Host + "/"
Console.WriteLine("Base URI: {0}", baseUri)
Dim sp As System.Net.ServicePoint = ServicePointManager.FindServicePoint(CType(uriList(i), Uri), httpProxy)
requestEvents(i) = New ManualResetEvent(False) GetUriResource(CType(uriList(i), Uri), requestEvents(i)) Next Console.WriteLine("Waiting...") ManualResetEvent.WaitAll(requestEvents) Console.WriteLine("Considered done...") Catch ex As Exception Console.WriteLine("Main() exception occurred: {0}", ex.Message) Finally Console.WriteLine("Something wrong here. What wrong? Find it yourself...") End Try End Sub End Class
|
To test this program we need to change the DLL to application (EXE) type program so that we can run it from the console. To complete this task, select the project folder > Right click mouse > Select Properties context menu. Change the Application type: to Console Application and the Startup object: to Sub Main.
Build the project.
Run the project.
The following is the output sample.
The following are the output samples when run from the command prompt with two and one URIs respectively. However an exception was thrown here and it is left for you to rectify it as an exercise!