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

Visual CSharp 2005 Recipes (2006) [eng]

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

348C 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

//Build the response using a StreamWriter feeding the

//Response.OutputStream.

StreamWriter sw =

new StreamWriter(context.Response.OutputStream, Encoding.UTF8);

sw.WriteLine("<html>");

sw.WriteLine("<head>"); sw.WriteLine("<title>Visual C# Recipes</title>"); sw.WriteLine("</head>");

sw.WriteLine("<body>");

sw.WriteLine("Recipe 10-5: " + result.AsyncState); sw.WriteLine("</body>");

sw.WriteLine("</html>");

sw.Flush();

//Configure the Response. context.Response.ContentType = "text/html"; context.Response.ContentEncoding = Encoding.UTF8;

//Close the Response to send it to the client. context.Response.Close();

Console.WriteLine("{0}: Sent HTTP response.", result.AsyncState);

}

catch (ObjectDisposedException)

{

Console.WriteLine("{0}: HttpListener disposed--shutting down.", result.AsyncState);

}

finally

{

// Start another handler if unless the HttpListener is closing. if (listener.IsListening)

{

Console.WriteLine("{0}: Creating new request handler.", result.AsyncState);

listener.BeginGetContext(RequestHandler, "RequestHandler_" + Interlocked.Increment(ref requestHandlerID));

}

}

}

public static void Main(string[] args)

{

//Quit gracefully if this feature is not supported. if (!HttpListener.IsSupported)

{

Console.WriteLine(

"You must be running this example on Windows XP SP2, ", "Windows Server 2003, or higher to create ",

"an HttpListener."); return;

}

//Create the HttpListener.

using (listener = new HttpListener())

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

349

{

//Configure the URI prefixes that will map to the HttpListener. listener.Prefixes.Add(

"http://localhost:19080/VisualCSharpRecipes/");

listener.Prefixes.Add( "http://localhost:20000/Recipe10-05/");

//Start the HttpListener before listening for incoming requests. Console.WriteLine("Starting HTTP Server");

listener.Start(); Console.WriteLine("HTTP Server started"); Console.WriteLine(Environment.NewLine);

//Create a number of asynchronous request handlers up to

//the configurable maximum. Give each a unique identifier.

for (int count = 0; count < maxRequestHandlers; count++)

{

listener.BeginGetContext(RequestHandler, "RequestHandler_" + Interlocked.Increment(ref requestHandlerID));

}

//Wait for the user to stop the HttpListener. Console.WriteLine("Press Enter to stop the HTTP Server"); Console.ReadLine();

//Stop accepting new requests.

listener.Stop();

// Terminate the HttpListener without processing current requests. listener.Abort();

}

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

}

}

}

10-6. Get an HTML Page from a Site That Requires Authentication

Problem

You need to retrieve a file from a web site, but the web site requires that you provide credentials for the purpose of authentication.

Solution

Use the System.Net.WebRequest and System.Net.WebResponse classes as described in recipe 10-4. Before making the request, configure the WebRequest.Credentials and WebRequest.Certificates properties with the necessary authentication information.

350 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

Tip You could also use the System.Net.WebClient class (discussed in recipe 10-3), which also has Credentials and Certificates properties that allow you to associate user credentials with a web request.

How It Works

Some web sites require user authentication information. When connecting through a browser, this information might be submitted transparently (for example, on a local intranet site that uses Windows integrated authentication), or the browser might request this information with a login dialog box. When accessing a web page programmatically, your code needs to submit this information. The approach you use depends on the type of authentication implemented by the web site:

If the web site is using basic or digest authentication, you can transmit a username and password combination by manually creating a new System.Net.NetworkCredential object and assigning it to the WebRequest.Credentials property. With digest authentication, you may also supply a domain name.

If the web site is using Windows integrated authentication, you can take the same approach and manually create a new System.Net.NetworkCredential object. Alternatively, you can retrieve the current user login information from the System.Net.CredentialCache object using the DefaultCredentials property.

If the web site requires a client certificate, you can load the certificate from a file using the

System.Security.Cryptography.X509Certificates.X509Certificate2 class and add that to the HttpWebRequest.ClientCertificates collection.

In the .NET Framework 2.0, you can load an X.509 certificate from a certificate store using the class System.Security.Cryptography.X509Certificates.X509Store defined in the System. Security.dll assembly. You can either find a certificate in the store programmatically using the X509Store.Certificates.Find method or present the user with a Windows dialog box and allow them to select the certificate. To present a dialog box, pass a collection of X.509 certificates contained in an X509Certificate2Collection object to the SelectFromCollection method of the System.Security.Cryptography.X509Certificates.X509Certificate2UI class.

The Code

The following example demonstrates all four of the basic approaches described previously. Note that you need to add a reference to the System.Security.dll assembly.

using System; using System.Net;

using System.Security.Cryptography.X509Certificates;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_06

{

public static void Main()

{

//Create a WebRequest that authenticates the user with a

//username and password combination over basic authentication. WebRequest requestA = WebRequest.Create("http://www.somesite.com"); requestA.Credentials = new NetworkCredential("userName", "password"); requestA.PreAuthenticate = true;

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

351

//Create a WebRequest that authenticates the current user

//with Windows integrated authentication.

WebRequest requestB = WebRequest.Create("http://www.somesite.com"); requestB.Credentials = CredentialCache.DefaultCredentials; requestB.PreAuthenticate = true;

//Create a WebRequest that authenticates the user with a client

//certificate loaded from a file.

HttpWebRequest requestC = (HttpWebRequest)WebRequest.Create("http://www.somesite.com");

X509Certificate cert1 = X509Certificate.CreateFromCertFile(@"..\..\TestCertificate.cer");

requestC.ClientCertificates.Add(cert1);

//Create a WebRequest that authenticates the user with a client

//certificate loaded from a certificate store. Try to find a

//certificate with a specific subject, but if it is not found

//present the user with a dialog so they can select the certificate

//to use from their personal store.

HttpWebRequest requestD = (HttpWebRequest)WebRequest.Create("http://www.somesite.com");

X509Store store = new X509Store(); X509Certificate2Collection certs =

store.Certificates.Find(X509FindType.FindBySubjectName, "Allen Jones", false);

if (certs.Count == 1)

{

requestD.ClientCertificates.Add(certs[0]);

}

else

{

certs = X509Certificate2UI.SelectFromCollection( store.Certificates,

"Select Certificate",

"Select the certificate to use for authentication.", X509SelectionFlag.SingleSelection);

if (certs.Count != 0)

{

requestD.ClientCertificates.Add(certs[0]);

}

}

// Now issue the request and process the responses...

}

}

}

10-7. Send E-mail Using SMTP

Problem

You need to send e-mail using an SMTP server.

Note

352 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 SmtpClient and MailMessage classes in the System.Net.Mail namespace.

In version 1.0 and 1.1 of the .NET Framework, you would send SMTP mail using the SmtpMail and MailMessage classes in the System.Web.Mail namespace from the System.Web.dll assembly. The SmtpClient and MailMessage classes discussed in this recipe are new to the System.dll assembly in the .NET Framework 2.0, and both simplify and extend the functionality provided by earlier versions.

How It Works

An instance of the SmtpClient class provides the mechanism through which you communicate with the SMTP server. You configure the SmtpClient using the properties described in Table 10-3.

Table 10-3. Properties of the SmtpClient Class

Property

Description

ClientCertificates

Gets a System.Security.Cryptography.X509Certificates.

 

X509CertificatesCollection to which you add the certificates to use

 

for communicating with the SMTP server (if required).

Credentials

Gets or sets an implementation of the System.Net.ICredentialsByHost

 

interface that represents the credentials to use to gain access to the

 

SMTP server. The CredentialCache and NetworkCredential classes

 

implement the ICredentialsByHost interface. Use NetworkCredential

 

if you want to specify a single set of credentials and CredentialCache if

 

you want to specify more than one.

EnableSsl

Gets or sets a bool value that indicates whether the SmtpClient should

 

use Secure Sockets Layer (SSL) to communicate with the SMTP server.

Host

Gets or sets a string containing the host name or IP address of the

 

SMTP server to use to send e-mail.

Port

Gets or sets an int value containing the port number to connect to on

 

the SMTP server. The default value is 25.

Timeout

Gets or sets an int value containing the time-out in milliseconds when

 

attempting to send e-mail. The default is 100 seconds.

UseDefaultCredentials

Gets or sets a bool value indicating whether the default user credentials are

 

used when communicating with the SMTP server. If true, the credentials

 

passed to the SMTP server are automatically obtained from the static

 

property CredentialCache.DefaultCredentials.

 

 

 

 

Tip You can specify default settings for the SmtpClient in the <mailSettings> section of your machine or application configuration files. Configurable default values include the host, port, username, and password.

Mail messages are represented by MailMessage objects, which you instantiate and then configure using the members summarized in Table 10-4.

Tip For simple mail messages, the MailMessage class provides a constructor that allows you to specify the from, to, subject, and body information for the mail message as string arguments—allowing you to create a complete mail message in a single call.

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

353

Table 10-4. Properties of the MailMessage Class

Property

Description

Attachments

Gets or sets a System.Net.Mail.AttachmentCollection containing the set of

 

attachments for the e-mail message. A System.Net.Mail.Attachment object

 

represents each attachment. You can create Attachment objects from files or

 

streams, and you can configure the encoding and content type for each

 

attachment.

Bcc

Gets or sets a System.Net.Mail.MailAddressCollection containing the blind

 

carbon copy addresses for the e-mail message. The MailAddressCollection

 

contains one or more MailAddress objects.

Body

Gets or sets a string value that contains the body text of the e-mail message.

BodyEncoding

Gets or sets a System.Text.Encoding object that specifies the encoding for the

 

body of the e-mail message. The default value is null resulting in a default

 

encoding of us-ascii, which is equivalent to the Encoding object returned by

 

the static property Encoding.ASCII.

CC

Gets or sets a System.Net.Mail.MailAddressCollection containing the carbon

 

copy addresses for the e-mail message. The MailAddressCollection contains

 

one or more MailAddress objects.

From

Gets or sets a System.Net.Mail.MailAddress containing the from address for

 

the e-mail message.

IsBodyHtml

Gets or sets a bool value identifying whether the body of the e-mail message

 

contains HTML.

ReplyTo

Gets or sets a System.Net.Mail.MailAddress containing the reply address for

 

the e-mail message.

Subject

Gets or sets a string containing the subject for the e-mail message.

SubjectEncoding

Gets or sets a System.Text.Encoding object that specifies the encoding used to

 

encode the body of the e-mail subject. The default value is null resulting in

 

a default encoding of us-ascii, which is equivalent to the Encoding object

 

returned by the static property Encoding.ASCII.

To

Gets or sets a System.Net.Mail.MailAddressCollection containing the

 

destination addresses for the e-mail message. The MailAddressCollection

 

contains one or more MailAddress objects.

 

 

Once you have configured the SmtpClient, you can send your MailMessage objects using the SmtpClient.Send method, which will cause your code to block until the send operation is completed or fails. Alternatively, you can send mail using a thread from the thread pool by calling the SendAsync method. When you call SendAsync, your code will be free to continue other processing while the e-mail is sent. Add an event handler to the SendCompleted event to receive notification that the asynchronous send has completed.

Note Remember that you can’t use SMTP to retrieve e-mail. For this task, you need the Post Office Protocol 3 (POP3) or the Internet Message Access Protocol (IMAP), neither of which is exposed natively in the .NET Framework.

The Code

The following example demonstrates how to use the SmtpClient class to send an e-mail message with multiple attachments to a set of recipients whose e-mail addresses are specified as commandline arguments:

354C 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

using System; using System.Net;

using System.Net.Mail;

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_07

{

public static void Main(string[] args)

{

//Create and configure the SmtpClient that will send the mail.

//Specify the host name of the SMTP server and the port used

//to send mail.

SmtpClient client = new SmtpClient("mail.somecompany.com", 25);

//Configure the SmtpClient with the credentials used to connect

//to the SMTP server.

client.Credentials =

new NetworkCredential("user@somecompany.com", "password");

// Create the MailMessage to represent the e-mail being sent. using (MailMessage msg = new MailMessage())

{

// Configure the e-mail sender and subject.

msg.From = new MailAddress("author@visual-csharp-recipes.com"); msg.Subject = "Greetings from Visual C# Recipes";

// Configure the e-mail body.

msg.Body = "This is a message from Recipe 10-07 of" +

"Visual C# Recipes. Attached is the source file " +

"and the binary for the recipe.";

//Attach the files to the e-mail message and set their MIME type. msg.Attachments.Add(

new Attachment(@"..\..\Recipe10-07.cs","text/plain")); msg.Attachments.Add(

new Attachment(@".\Recipe10-07.exe", "application/octet-stream"));

//Iterate through the set of recipients specified on the

//command line. Add all addresses with the correct structure as

//recipients.

foreach (string str in args)

{

//Create a MailAddress from each value on the command line

//and add it to the set of recipients.

try

{

msg.To.Add(new MailAddress(str));

}

catch (FormatException ex)

{

// Proceed to the next specified recipient. Console.WriteLine("{0}: Error -- {1}", str, ex.Message); continue;

}

}

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

355

// Send the message. client.Send(msg);

}

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

}

}

}

10-8. Resolve a Host Name to an IP Address

Problem

You want to determine the IP address for a computer based on its fully qualified domain name by performing a DNS query.

Solution

In version 2.0 of the .NET Framework, use the method GetHostEntry of the System.Net.Dns class, and pass the computer’s fully qualified domain name as a string parameter.

Note In version 1.0 and 1.1 of the .NET Framework, you should use the method GetHostByName of the Dns class, but it is marked as obsolete in version 2.0.

How It Works

On the Internet, the human-readable names that refer to computers are mapped to IP addresses, which is what TCP/IP requires in order to communicate between computers. For example, the name www.apress.com might be mapped to the IP address 65.19.150.100. To determine the IP address for a given name, the computer contacts a DNS server. The name or IP address of the DNS server contacted is configured as part of a computer’s network configuration.

The entire process of name resolution is transparent if you use the System.Net.Dns class, which allows you to retrieve the IP address for a host name by calling GetHostEntry.

Tip The Dns class also provides the BeginGetHostEntry and EndGetHostEntry methods that allow you to resolve IP addresses asynchronously. Also, the static method GetHostName returns the computer name of the local machine.

The Code

The following example retrieves the IP addresses of all computers whose fully qualified domain names are specified as command-line arguments:

using System; using System.Net;

356 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

namespace Apress.VisualCSharpRecipes.Chapter10

{

class Recipe10_08

{

public static void Main(string[] args)

{

foreach (string comp in args)

{

try

{

//Retrieve the DNS entry for the specified computer. IPAddress[] addresses = Dns.GetHostEntry(comp).AddressList;

//The DNS entry may contain more than one IP address. Iterate

//through them and display each one along with the type of

//address (AddressFamily).

foreach (IPAddress address in addresses)

{

Console.WriteLine("{0} = {1} ({2})", comp, address, address.AddressFamily);

}

}

catch (Exception ex)

{

Console.WriteLine("{0} = Error ({1})", comp, ex.Message);

}

}

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

}

}

}

Usage

Running the example with the following command line:

recipe10-08 www.apress.com www.microsoft.com localhost somejunk

will produce the following output. Notice that multiple IP addresses are returned for some host names.

www.apress.com = 65.19.150.100 (InterNetwork) www.microsoft.com = 207.46.198.30 (InterNetwork) www.microsoft.com = 207.46.20.30 (InterNetwork) www.microsoft.com = 207.46.20.60 (InterNetwork) www.microsoft.com = 207.46.18.30 (InterNetwork) www.microsoft.com = 207.46.19.30 (InterNetwork) www.microsoft.com = 207.46.19.60 (InterNetwork) www.microsoft.com = 207.46.199.30 (InterNetwork) www.microsoft.com = 207.46.198.60 (InterNetwork) localhost = 127.0.0.1 (InterNetwork)

somejunk = Error (No such host is known)

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

357

10-9. Ping an IP Address

Problem

You want to check to see whether a computer is online and accessible and gauge its response time.

Solution

Send a ping message. This message is sent using the ICMP, accessible through the Send method of the System.Net.NetworkInformation.Ping class.

Note The Ping class is new to the .NET Framework 2.0. To send a ping message in earlier versions of the .NET Framework, you had to undertake significant effort to manually create an ICMP request message using raw sockets and lengthy code.

How It Works

A ping message contacts a device at a specific IP address, passing it a test packet, and requests that the remote device respond by echoing back the packet. To gauge the connection latency between two computers, you can measure the time taken for a ping response to be received.

Caution Many commercial Web sites do not respond to ping requests because they represent an unnecessary processing overhead and are often used in denial of service attacks. The firewall that protects the site will usually filter them out before they reach the specified destination. This will cause your ping request to time out.

The Ping class allows you to send ping messages using the Send method. The Send method provides a number of overloads, which allow you to specify some or all of the following:

The IP address or host name of the target computer. You can specify this as a string or a System.Net.IPAddress object.

The number of milliseconds to wait for a response before the request times out (specified as an int) with the default set to 5000.

A byte array of up to 65,500 data bytes that is sent with the ping request and that should be returned in the response.

A System.Net.NetworkInformation.PingOptions object that specifies time-to-live and fragmentation options for the transmission of the ping message.

The Send method will return a System.Net.NetworkInformation.PingReply object. The Status property of the PingReply will contain a value from the System.Net.NetworkInformation.IPStatus enumeration from which you can determine the result of the ping request. The most common values will be Success and TimedOut. If the host name you pass to the Send method cannot be resolved, Send will throw an exception, but you must look at the InnerException to determine the cause of the problem.

The Ping class also provides a SendAsync method that performs the ping request using a thread-pool thread so that the calling thread does not block. When the ping is finished or fails because of a time-out, the thread raises the PingCompleted event on the Ping object, which you can handle using a method that matches the signature of the System.Net.NetworkInformation.PingCompletedEventHandler delegate. However, the Ping object can handle only a single concurrent request; otherwise, it will throw a System.InvalidOperationException.

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