Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Visual CSharp 2005 Recipes (2006) [eng]

.pdf
Скачиваний:
49
Добавлен:
16.08.2013
Размер:
4.04 Mб
Скачать

338 C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

The Code

The following example uses the members of the NetworkInterface class to display information about all the network interfaces on the local machine:

using System;

using System.Net.NetworkInformation;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_01

{

static void Main()

{

// Only proceed if there is a network available. if (NetworkInterface.GetIsNetworkAvailable())

{

//Get the set of all NetworkInterface objects for the local

//machine.

NetworkInterface[] interfaces =

NetworkInterface.GetAllNetworkInterfaces();

// Iterate through the interfaces and display information. foreach (NetworkInterface ni in interfaces)

{

//Report basic interface information. Console.WriteLine("Interface Name: {0}", ni.Name); Console.WriteLine(" Description: {0}", ni.Description); Console.WriteLine(" ID: {0}", ni.Id); Console.WriteLine(" Type: {0}", ni.NetworkInterfaceType); Console.WriteLine(" Speed: {0}", ni.Speed); Console.WriteLine(" Status: {0}", ni.OperationalStatus);

//Report physical address.

Console.WriteLine(" Physical Address: {0}", ni.GetPhysicalAddress().ToString());

//Report network statistics for the interface. Console.WriteLine(" Bytes Sent: {0}",

ni.GetIPv4Statistics().BytesSent); Console.WriteLine(" Bytes Received: {0}", ni.GetIPv4Statistics().BytesReceived);

//Report IP configuration. Console.WriteLine(" IP Addresses:"); foreach (UnicastIPAddressInformation addr

in ni.GetIPProperties().UnicastAddresses)

{

Console.WriteLine("

- {0} (lease expires {1})",

addr.Address,

 

DateTime.Now +

new TimeSpan(0, 0, (int)addr.DhcpLeaseLifetime));

}

Console.WriteLine(Environment.NewLine);

}

}

C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

339

else

{

Console.WriteLine("No network available.");

}

// Wait to continue. Console.WriteLine(Environment.NewLine); Console.WriteLine("Main method complete. Press Enter"); Console.ReadLine();

}

}

}

10-2. Detect Changes in Network Connectivity

Problem

You need a mechanism to check whether changes to the network occur during the life of your application.

Solution

Add handlers to the static NetworkAddressChanged and NetworkAvailabilityChanged events implemented by the System.Net.NetworkInformation.NetworkChange class.

How It Works

The NetworkChange class (new to the .NET Framework 2.0) provides an easy-to-use mechanism that allows applications to be aware of changes to network addresses and general network availability. This allows your applications to adapt dynamically to the availability and configuration of the network.

The NetworkAvailabilityChanged event fires when a change occurs to general network availability. An instance of the NetworkAvailabilityChangedEventHandler delegate is needed to handle this event and is passed a NetworkAvailabilityEventArgs object when the event fires. The NetworkAvailabilityEventArgs.IsAvailable property returns a bool indicating whether the network is available or unavailable following the change.

The NetworkAddressChanged event fires when the IP address of a network interface changes. An instance of the NetworkAddressChangedEventHandler delegate is required to handle these events. No event-specific arguments are passed to the event handler, which must call NetworkInterface. GetAllNetworkInterfaces (discussed in recipe 10-1) to determine what has changed and to take appropriate action.

The Code

The following example demonstrates how to use handlers that catch NetworkAddressChanged and NetworkAvailabilityChanged events and then displays status information to the console:

using System;

using System.Net.NetworkInformation;

340C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_02

{

//Declare a method to handle NetworkAvailabilityChanged events. private static void NetworkAvailabilityChanged(

object sender, NetworkAvailabilityEventArgs e)

{

//Report whether the network is now available or unavailable.

if (e.IsAvailable)

{

Console.WriteLine("Network Available");

}

else

{

Console.WriteLine("Network Unavailable");

}

}

// Declare a method to handle NetworkAdressChanged events.

private static void NetworkAddressChanged(object sender, EventArgs e)

{

Console.WriteLine("Current IP Addresses:");

// Iterate through the interfaces and display information. foreach (NetworkInterface ni in

NetworkInterface.GetAllNetworkInterfaces())

{

foreach (UnicastIPAddressInformation addr

in ni.GetIPProperties().UnicastAddresses)

{

Console.WriteLine(" - {0} (lease expires {1})", addr.Address, DateTime.Now +

new TimeSpan(0, 0, (int)addr.DhcpLeaseLifetime));

}

}

}

static void Main(string[] args)

{

//Add the handlers to the NetworkChange events. NetworkChange.NetworkAvailabilityChanged +=

NetworkAvailabilityChanged; NetworkChange.NetworkAddressChanged +=

NetworkAddressChanged;

//Wait to continue. Console.WriteLine(Environment.NewLine);

Console.WriteLine("Press Enter to stop waiting for network events"); Console.ReadLine();

}

}

}

C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

341

10-3. Download Data over HTTP or FTP

Problem

You need a quick, simple way to download data from the Internet using HTTP or FTP.

Solution

Use the methods of the System.Net.WebClient class.

How It Works

The .NET Framework provides several mechanisms for transferring data over the Internet. One of the easiest approaches is to use the System.Net.WebClient class. WebClient provides many high-level methods that simplify the transfer of data by specifying the source as a uniform resource identifier (URI); Table 10-2 summarizes them. The URI can specify that a file (file://), FTP (ftp://), or HTTP (http:// or https://) scheme be used to download the resource.

Table 10-2. Data Download Methods of the WebClient Class

Method

Description

OpenRead

Returns a System.IO.Stream that provides access to the data from

 

a specified URI.

OpenReadAsync

Same as OpenRead but performs the data transfer using a thread-pool

 

thread so that the calling thread does not block. Add an event handler to

 

the OpenReadCompleted event to receive notification that the operation has

 

completed. (This is new to the .NET Framework 2.0.)

DownloadData

Returns a byte array that contains the data from a specified URI.

DownloadDataAsync

Same as DownloadData but performs the data transfer using a thread-pool

 

thread so that the calling thread does not block. Add an event handler to

 

the DownloadDataCompleted event to receive notification that the operation

 

has completed. (This is new to the .NET Framework 2.0.)

DownloadFile

Downloads data from a specified URI and saves it to a specified local file.

DownloadFileAsync

Same as DownloadFile but performs the data transfer using a thread-pool

 

thread so that the calling thread does not block. Add an event handler to

 

the DownLoadFileCompleted event to receive notification that the operation

 

has completed. (This is new to the .NET Framework 2.0.)

DownloadString

Returns a string that contains the data from a specified URI. (This is new

 

to the .NET Framework 2.0.)

DownloadStringAsync

Same as DownloadString but performs the data transfer using a thread-pool

 

thread so that the calling thread does not block. Add an event handler to

 

the DownloadStringCompleted event to receive notification that the operation

 

has completed. (This is new to the .NET Framework 2.0.)

 

 

The asynchronous download methods added in version 2.0 of the .NET Framework allow you to download data as a background task using a thread from the thread pool (discussed in recipe 4-1). When the download is finished or fails, the thread calls the appropriate OnXXX virtual methods that raise the corresponding event on the WebClient object, which you can handle using a method that matches the signature of the System.ComponentModel.AsyncCompletedEventHandler delegate if you don’t want to derive a type from WebClient and override the virtual method. However, the WebClient

342C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

object can handle only a single concurrent asynchronous download, making a WebClient object suitable for the background download of large single sets of data but not for the download of many files concurrently. (You could, of course, create multiple WebClient objects to handle multiple downloads.) You can cancel the outstanding asynchronous download using the method CancelAsync.

Tip The WebClient class derives from System.ComponentModel.Component, so you can add it to the Visual Studio 2005 Form Designer Toolbox in order to allow you to easily set the properties or define the event handlers in a Windows Forms–based application.

The Code

The following example downloads a specified resource from a URI as a string and, since it is an HTML page, parses it for any fully qualified URLs that refer to GIF files. It then downloads each of these files to the local hard drive.

using System; using System.IO; using System.Net;

using System.Text.RegularExpressions;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_03

{

private static void Main()

{

//Specify the URI of the resource to parse. string remoteUri = "http://www.apress.com";

//Create a WebClient to perform the download. WebClient client = new WebClient();

Console.WriteLine("Downloading {0}", remoteUri);

//Perform the download getting the resource as a string. string str = client.DownloadString(remoteUri);

//Use a regular expression to extract all fully qualified

//URIs that refer to GIF files.

MatchCollection matches =

Regex.Matches(str,@"http\S+[^-,;:?]\.gif");

// Try to download each referenced .gif file. foreach(Match match in matches)

{

foreach(Group grp in match.Groups)

{

// Determine the local filename. string file =

grp.Value.Substring(grp.Value.LastIndexOf('/')+1);

try

{

// Download and store the file.

C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

343

Console.WriteLine("Downloading {0} to file {1}", grp.Value, file);

client.DownloadFile(new Uri(grp.Value), file);

}

catch

{

Console.WriteLine("Failed to download {0}", grp.Value);

}

}

}

// Wait to continue. Console.WriteLine(Environment.NewLine); Console.WriteLine("Main method complete. Press Enter"); Console.ReadLine();

}

}

}

Note The regular expression used in the example is simple and is not designed to cater to all possible URL structures. Recipes 2-5 and 2-6 discuss regular expressions.

Notes

You may also want to upload data to resources specified as a URI, although this technique is not as commonly used. The WebClient class also provides methods for performing uploads that are equivalent to the download methods discussed previously.

OpenWrite

OpenWriteAsync

UploadData

UploadDataAsync

UploadFile

UploadFileAsync

UploadString

UploadStringAsync

10-4. Download a File and Process It Using

a Stream

Problem

You need to retrieve a file from a web site, but you do not want or do not have permission to save it directly to the hard drive. Instead, you want to process the data in your application directly in memory.

344 C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

Solution

Use the System.Net.WebRequest class to create your request, the System.Net.WebResponse class to retrieve the response from the web server, and some form of reader (typically a System.IO.StreamReader for HTML or text data or a System.IO.BinaryReader for a binary file) to parse the response data.

Tip You could also use the OpenRead method of the System.Net.WebClient class to open a stream. However, the additional capabilities of the WebRequest and WebResponse classes give you more control over the operation of the network request.

How It Works

Opening and downloading a stream of data from the Web using the WebRequest and WebResponse classes takes the following four basic steps:

1.Use the static method Create of the WebRequest class to specify the page you want. This method returns a WebRequest-derived object, depending on the type of URI you specify. For example, if you use an HTTP URI (with the scheme http:// or https://), you will create an HttpWebRequest instance. If you use a file system URI (with the scheme file://), you will create a FileWebRequest instance. In the .NET Framework 2.0, you can also use an FTP URL (with the scheme ftp://), which will create an FtpWebRequest.

2.Use the GetResponse method of the WebRequest object to return a WebResponse object for the page. If the request times out, a System.Net.WebException will be thrown. You can configure the time-out for the network request through the WebRequest.Timeout property in milliseconds (the default value is 100000).

3.Create a StreamReader or a BinaryReader that wraps the stream returned by the WebResponse. GetResponseStream method.

4.Perform any steps you need to with the stream contents.

The Code

The following example retrieves and displays a graphic and the HTML content of a web page. Figure 10-1 shows the output.

using System; using System.Net; using System.IO;

using System.Drawing; using System.Windows.Forms;

namespace Apress.VisualCSharpRecipes.Chapter10

{

public partial class Recipe10_04 : Form

{

public Recipe10_04()

{

InitializeComponent();

}

protected override void OnLoad(EventArgs e)

{

base.OnLoad(e);

C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

345

string picUri = "http://www.apress.com/img/img05/Hex_RGB4.jpg"; string htmlUri = "http://www.apress.com";

// Create the requests.

WebRequest requestPic = WebRequest.Create(picUri); WebRequest requestHtml = WebRequest.Create(htmlUri);

//Get the responses.

//This takes the most significant amount of time, particularly

//if the file is large, because the whole response is retrieved. WebResponse responsePic = requestPic.GetResponse();

WebResponse responseHtml = requestHtml.GetResponse();

//Read the image from the response stream.

pictureBox1.Image = Image.FromStream(responsePic.GetResponseStream());

// Read the text from the response stream. using (StreamReader r =

new StreamReader(responseHtml.GetResponseStream()))

{

textBox1.Text = r.ReadToEnd();

}

}

[STAThread]

public static void Main(string[] args)

{

Application.Run(new Recipe10_04());

}

}

}

Figure 10-1. Downloading content from the Web using a Stream

Note

346 C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

10-5. Respond to HTTP Requests from Your Application

Problem

You want your application to be able to respond to HTTP requests programmatically.

Solution

Use the new System.Net.HttpListener class provided by the .NET Framework 2.0.

Your application must be running on Windows XP Service Pack 2 (or later) or Windows 2003 to use the

HttpListener class; otherwise, a System.PlatformNotSupportedException will be thrown when you try to instantiate it. You should check the bool returned by the static property HttpListener.IsSupported to check whether support is available.

How It Works

The HttpListener class provides an easy-to-use mechanism through which your programs can accept and respond to HTTP requests. To use the HttpListener class, follow these steps:

1.Instantiate an HttpListener object.

2.Configure the URI prefixes that the HttpListener object will handle using the Prefixes property. The Prefixes property returns a System.Net.HttpListenerPrefixCollection collection to which you can add URI prefixes (as strings) using the Add method. Each prefix must end with a forward slash (/), or an System.ArgumentException is thrown. If you specify a URL prefix that is already being handled, a System.Net.HttpListenerException is thrown. When a client makes a request, the request will be handled by the listener configured with the prefix that most closely matches the client’s requested URL.

3.Start the HttpListener object by calling its Start method. You must call Start before the HttpListener object can accept and process HTTP requests.

4.Accept client requests using the GetContext method of the HttpListener object. The GetContext method will block the calling thread until a request is received and then returns a System.Net.HttpListenerContext object. Alternatively, you can use the BeginGetContext and

EndGetContext methods to listen for requests on a thread-pool thread. When a request is received, the System.AsynchCallback delegate specified as the argument to the BeginGetContext method will be called and passed the HttpListenerContext object. Regardless of how it is obtained, the HttpListenerContext objects implements three read-only properties critical to the handling of a client request:

The Request property returns a System.Net.HttpListenerRequest through which you can access details of the client’s request.

The Response property returns a System.Net.HttpListenerResponse through which you can configure the response to send to the client.

The User property returns an instance of a type implementing System.Security.Principal. IPrincipal, which you can use to obtain identity, authentication, and authorization information about the user associated with the request.

C H A P T E R 1 0 N E T W O R K I N G A N D R E M OT I N G

347

5.Configure the HTTP response through the members of the HttpListenerResponse object accessible through the HttpListenerContext.Response property.

6.Send the response by calling the Close method of the HttpListenerResponse object.

7.Once you have finished processing HTTP requests, call Stop on the HttpListener object to stop accepting more requests. Call Close to shut down the HttpListener object, which will wait until all outstanding requests have been processed, or call Abort to terminate the HttpListener object without waiting for requests to be complete.

The Code

The following example demonstrates how to use the HttpListener class to process HTTP requests. The example starts listening for five requests concurrently using the asynchronous BeginGetContext method and handles the response to each request by calling the RequestHandler method. Each time a request is handled, a new call is made to BeginGetContext so that you always have the capacity to handle up to five requests.

To open a connection to the example from your browser, enter the URL http://localhost:19080/ VisualCSharpRecipes/ or http://localhost:20000/Recipe10-05/, and you will see the response from the appropriate request handler.

using System; using System.IO; using System.Net; using System.Text;

using System.Threading;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_05

{

//Configure the maximum number of request that can be

//handled concurrently.

private static int maxRequestHandlers = 5;

//An integer used to assign each HTTP request handler a unique

//identifier.

private static int requestHandlerID = 0;

//The HttpListener is the class that provides all the capabilities

//to receive and process HTTP requests.

private static HttpListener listener;

//A method to asynchronously process individual requests and send

//responses.

private static void RequestHandler(IAsyncResult result)

{

Console.WriteLine("{0}: Activated.", result.AsyncState);

try

{

// Obtain the HttpListenerContext for the new request. HttpListenerContext context = listener.EndGetContext(result);

Console.WriteLine("{0}: Processing HTTP Request from {1} ({2}).", result.AsyncState,

context.Request.UserHostName,

context.Request.RemoteEndPoint);

Соседние файлы в предмете Программирование на C++