What’s in This Chapter
Wrox.com Downloads for This Chapter
Please note that all the code examples for this chapter are available as a part of this chapter’s code download on the book’s website at www.wrox.com/go/csharp5programmersref on the Download Code tab.
Networking is a complicated topic. Understanding all the protocols, addresses, routing, data layers, network hardware, and everything else that goes into building a network is a difficult task and outside the scope of this book.
Fortunately, most programs use only a few main networking techniques such as:
Rather than trying to cover all there is to know about network programming in detail, this chapter explains how to perform these common chores.
If you want to get into network programming, you should look for a book that focuses on just that. If you search your favorite online bookstore for C# Networking, you should find a few good choices. You can also look at the following articles.
The .NET Framework defines several namespaces containing networking classes. Most of those namespaces, and some of the most useful classes, are contained in the System.Net
namespace.
At the lower levels, the System.Net.Sockets
namespace provides classes that manipulate Windows sockets (Winsock). These let you create and manage sockets, which provide relatively low-level access to the network. Sockets let you accept incoming connection requests, connect to remote hosts, and send and receive datagrams.
The HttpListener
class lets you create a listener that responds to HTTP requests. Using a listener, you can make a program that runs on a server and responds to incoming requests from other programs.
The WebRequest
and WebResponse
classes are abstract classes that define a request/response model for fetching URIs. A program uses a class derived from WebRequest
to request a URL (for example, a web page). When the file returns from the network, the program receives a WebResponse
object fulfilling the request (if nothing went wrong). Classes derived from WebRequest
include FileWebRequest
, FtpWebRequest
, and HttpWebRequest
. Similarly classes derived from WebResponse
include FileWebResponse
, FtpWebResponse
, and HttpWebResponse
.
The WebClient
class provides some of the same features as the request/response classes but at a higher level. It’s not quite as flexible, but it’s much easier to use.
The System.Net.Mail
namespace includes classes for sending e-mail messages to a Simple Mail Transfer Protocol (SMTP) server so that they can be forwarded to the recipient(s).
The following sections explain how you can use these classes to download and upload information, get information about remote files and directories, and send e-mail.
The following sections explain how to download data using WebClient
and WebRequest
classes. It’s easier to use WebClient
, so I recommend that you try that approach first. The WebRequest
class gives you more control over cookies, request and response headers, and other details that don’t matter for simple file uploads and downloads.
The WebClient
class provides four sets of methods for downloading data from a URL into a file, string
, byte
array, or stream. Each set has one synchronous and two asynchronous methods. The following sections describe these four sets of methods.
The WebClient
class’s first set of methods downloads the data at a URL into a local file. Its methods are DownloadFile
, DownloadFileAsync
, and DownloadFileTaskAsync
. The synchronous method, DownloadFile
, is remarkably easy to use. Simply create a new object and call the method, passing it the URL of the file you want to download and the name of the file where you want to place the result. The following code shows an example.
WebClient client = new WebClient();
client.DownloadFile(
"http://www.csharphelper.com/howto_index.html",
"howto_index.html");
This code downloads the web page http://www.csharphelper.com/howto_index.html
and stores it in the local file howto_index.html
. The new file is placed in the program’s current directory, which by default is its startup directory.
The DownloadFileAsync
method starts an asynchronous file download. You can catch the WebClient
’s DownloadProgressChanged
event to monitor the download’s progress. Catch the DownloadFileCompleted
event to get the result of the download. While the download is in progress, you can cancel it by calling the WebClient
’s CancelAsync
method.
The second asynchronous file download method is DownloadFileTaskAsync
. Like DownloadFileAsync
, this method starts an asynchronous download. The difference is that this method uses a separate task to start the download, so you can use the await
keyword to wait for the method to finish downloading the file. The code runs asynchronously and then execution resumes after the await
keyword when the asynchronous task has finished. (For more information on await
, see the section “Using async
and await
” in Chapter 6, “Methods.”)
The WebClient
class’s second set of downloading methods is similar to the first set, except it downloads data into a string
instead of a file. The string downloading methods are DownloadString
, DownloadStringAsync
, and DownloadStringTaskAsync
.
As is the case when you download a file asynchronously, you can catch the DownloadProgressChanged
event to monitor the download’s progress, and you can use the CancelAsync
method to cancel the download. Catch the DownloadStringCompleted
event to get the downloaded string.
The DownloadStringAsync example program, which is available for download on this book’s website, uses code similar to the following to download a web page as a string
. (The code isn’t exactly the same because the program has some extra user interface code that makes the program easier to use, but that isn’t part of the download process.)
// The WebClient. (Needed for canceling.)
private WebClient Client = null;
// Start downloading.
private void downloadButton_Click(object sender, EventArgs e)
{
// Make a Uri.
Uri uri = new Uri(urlTextBox.Text);
// Start the download.
Client = new WebClient();
Client.DownloadProgressChanged += Client_DownloadProgressChanged;
Client.DownloadStringCompleted += Client_DownloadStringCompleted;
Client.DownloadStringAsync(uri);
}
// Report on download progress.
private void Client_DownloadProgressChanged(object sender,
DownloadProgressChangedEventArgs e)
{
downloadProgressBar.Value = e.ProgressPercentage;
downloadStatusLabel.Text = e.ProgressPercentage.ToString() + "%";
}
// The download has finished.
void Client_DownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
// See what the result was.
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
MessageBox.Show("Canceled");
}
else
{
// Display the downloaded file.
MessageBox.Show(e.Result);
}
Client.Dispose();
}
// Cancel the download.
private void cancelButton_Click(object sender, EventArgs e)
{
// Cancel.
Client.CancelAsync();
}
The program declares a WebClient
at the module level, so it is visible to all the program’s methods, in particular the methods that start and cancel the download.
When you click the program’s Download button, the downloadButton_Click
event handler starts the download. It first creates a Uri
object to represent the URL to download. (The Async
methods take a Uri
object as a parameter. The synchronous and TaskAsync
methods can take either a string
or a Uri
as a parameter.)
This is a bit different from the DownloadFile
method, which can take the URL as a string
parameter. The DownloadString
method requires a Uri
object.
The code creates a new WebClient
object, associates event handlers with the DownloadProgressChanged
and DownloadStringCompleted
events, and then calls the DownloadStringAsync
method to start the download.
The DownloadProgressChanged
event handler updates a ToolStripProgressBar
and a ToolStripStatusLabel
to keep the user informed of the progress. The e.ProgressPercentage
parameter is an int
holding the percentage of the download that is complete.
The DownloadStringCompleted
event handler checks the result to see if there was an error or if the download was canceled. If the download completed successfully, the result string is stored in the e.Result
parameter.
If the user clicks the program’s Cancel button before the download completes, the cancelButton_Click
event handler calls the WebClient
’s CancelAsync
method.
Figure 20-1 shows the DownloadStringAsync example program displaying a web page from the C# Helper website.
The WebClient
class’s third set of downloading methods is similar to the first two except it downloads data into a byte
array. Its methods are DownloadData
, DownloadDataAsync
, and DownloadDataTaskAsync
.
As before, when you download data asynchronously, you can catch the DownloadProgressChanged
event to monitor the download’s progress, and you can use the CancelAsync
method to cancel the download. Catch the DownloadDataCompleted
event to get the downloaded bytes.
The WebClient
class’s final set of downloading methods is somewhat similar to the others, but the fact that these methods download data in a stream lead to some differences. This group’s methods are OpenRead
, OpenReadAsync
, and OpenReadTaskAsync
.
The asynchronous methods do not fire the DownloadProgressChanged
event, so you cannot monitor the download’s progress, but you can still use the CancelAsync
method to cancel the download.
Catch the OpenReadCompleted
event to process the stream. If the download was successful, the e.Result
parameter contains the stream.
To download data with a WebRequest
object, use the WebRequest
class’s Create
method to create a new object. This method takes as a parameter either a URL or a Uri
object. The method examines its parameter and returns an appropriate object of a class that inherits from WebRequest
. For example, if the URL string begins with http://
, the Create
method returns an HttpWebRequest
object. Usually, you can ignore the specific class and just treat the result as a WebRequest
.
After you create the request object, set its Method
property to indicate the type of operation you want to perform. The WebRequestMethods
namespace defines the three classes Http
, Ftp
, and File
that provide strings that define methods that you can use. For example, WebRequestMethods.Http.Get
represents a download command that uses the HTTP protocol.
The following table briefly summarizes the HTTP methods, which are the most confusing.
Method | Purpose |
Connect | Represents an HTTP CONNECT command for use with a proxy. |
Get | Represents an HTTP GET command, which downloads a resource. |
Head | Represents an HTTP HEAD command. This is similar to a GET command except it returns only headers and not the actual resource. |
MkCol | Represents an HTTP MKCOL command, which creates a new collection (for example, a collection of pages). |
Post | Represents an HTTP POST command, which basically creates a new resource. |
Put | Represents an HTTP PUT command, which can create or update a resource. |
The Ftp
and File
methods are more self-explanatory. The following list shows the Ftp
methods.
AppendFile
DeleteFile
DownloadFile
GetDateTimeStamp
GetFileSize
ListDirectory
ListDirectoryDetails
MakeDirectory
PrintWorkingDirectory
RemoveDirectory
Rename
UploadFile
UploadFileWithUniqueName
The WebRequestMethods.File
class defines only two methods, both of which have self-explanatory names: DownloadFile
and UploadFile
.
After you create the WebRequest
object and set its Method
property, call the request’s GetResponse
method to get a WebResponse
object.
You can examine the response’s properties to get information about the response. For example, you can look at the ContentLength
and ContentType
properties to learn about the response’s contents. The IsFromCache
property indicates whether the contents were loaded from cache or from the original source.
The response’s GetResponseStream
method returns a stream that contains the requested content (if nothing went wrong). Now you can write code to use this stream to process the content appropriately.
The following list summarizes the steps for using a WebRequest
.
WebRequest.Create
to create the request object.Method
property.GetResponse
method to get a WebResponse
.GetResponseStream
method to get the response stream.The WebRequestDownloadData example program, which is available for download on this book’s website, uses the following code to download an image file from an http://
URL.
try
{
// Make the WebRequest.
WebRequest request = WebRequest.Create(urlTextBox.Text);
// Use the Get method to download the file.
request.Method = WebRequestMethods.Http.Get;
// Get the response.
WebResponse response = request.GetResponse();
// Get the image from the response stream.
// (You must close the stream when finished.)
using (Stream stream = response.GetResponseStream())
{
Bitmap bitmap = new Bitmap(stream);
// Display the result.
imagePictureBox.Image = bitmap;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Most of this code follows the basic steps fairly closely. The only new part is the code that processes the stream. In this example, the program passes the stream to the Bitmap
class’s constructor to create a copy of the downloaded image. The code then displays the Bitmap
in a PictureBox
.
Figure 20-2 shows the WebRequestDownloadData example program displaying an image downloaded from the Internet.
You can use the WebClient
and WebRequest
classes to upload data as well as download it. The process is fairly similar to the steps you follow for downloading resources, with a few changes to the methods you use. The following sections explain how you can use the WebClient
and WebRequest
classes to upload data.
Using a WebClient
to upload a file is similar to using a WebClient
to download a file. One big difference, however, is security.
Most of the Internet’s material is freely available for download, but to upload anything you usually need a username and password for the destination server. In most cases you can supply those by setting the WebRequest
’s Credentials
property to a NetworkCredential
object.
The following code shows how a program could use a WebClient
to upload a file.
WebClient client = new WebClient();
client.Credentials = new NetworkCredential(username, password);
client.UploadFile(url, filename);
The WebClient
class’s UploadFile
, UploadData
, and UploadString
methods correspond to their downloading counterparts. They also come in the asynchronous versions UploadFileAsync
, UploadDataAsync
, and UploadStringAsync
.
The OpenWrite
and OpenWriteAsync
methods open streams into which the program can write. (These correspond to the OpenRead
and OpenReadAsync
methods that open streams for reading downloaded data.)
The UploadValues
and UploadValuesAsync
methods send a name/value collection for the server to process in some way.
When you use a WebRequest
object to download data, you get a stream from a WebResponse
object and then process the data in the stream. To use a WebRequest
object to upload data, you get a stream and write data into it.
The following list summarizes the steps for using a WebRequest
to upload a file.
WebRequest
object’s Create
method to create a WebRequest
object.WebRequest
’s Method
property to indicate the method that you want to perform.WebRequest
’s Credentials
property to specify the username and password you want to use on the server.WebRequest
’s GetRequestStream
method to get a stream.The following code shows how a program might use a WebRequest
object to upload a byte array (highlighted in bold).
// Make the WebRequest.
WebRequest request = WebRequest.Create(url);
// Use the UploadFile method.
request.Method = WebRequestMethods.Ftp.UploadFile;
// Set network credentials.
request.Credentials = new NetworkCredential(username, password);
// Write the bytes into the request stream.
using (Stream stream = request.GetRequestStream())
{
stream.Write(bytes, 0, bytes.Length);
}
From here, you can upload a file, string
, image, or other data by converting it into a byte
array and then using similar code to upload the array.
File Transfer Protocol (FTP) defines protocols for transferring files from one host to another on a Transmission Control Protocol (TCP) network such as the Internet.
These transfers are more storage-oriented than a typical Internet user’s browser uses. A user typically uses a web browser to request a file and the browser displays it. FTP transfers typically move files, for example, between your computer and a host somewhere on the Internet.
FTP also allows you to ask a server file-related questions. For example, it lets you ask a server for a file’s size or for a directory listing.
In addition to letting you upload and download files, the WebRequest
class also lets you perform FTP queries. The steps are similar to those you use to download files.
WebRequest.Create
to create the request object.Method
property, in this case to an FTP method.Credentials
property.GetResponse
method to get a WebResponse
.GetResponseStream
method to get the response stream.The FtpGetFileInfo example program, which is available for download on this book’s website, uses the following code to get the length of a file.
// Use FTP to get a remote file's size.
private long FtpGetFileSize(string url, string username, string password)
{
// Make a FtpRequest object.
WebRequest request = WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.GetFileSize;
// Set network credentials.
request.Credentials = new NetworkCredential(username, password);
using (WebResponse response = request.GetResponse())
{
// Return the size.
return response.ContentLength;
}
}
This code simply follows the steps outlined earlier.
The program uses the following code to get a file’s last modification time.
// Use FTP to get a remote file's timestamp.
private DateTime FtpGetFileTimestamp(string uri, string username, string password)
{
// Get the object used to communicate with the server.
WebRequest request = WebRequest.Create(uri);
request.Method = WebRequestMethods.Ftp.GetDateTimestamp;
// Get network credentials.
request.Credentials = new NetworkCredential(username, password);
// Return the last modification time.
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
return response.LastModified;
}
}
This code also follows the previously described steps but with one twist. The LastModified
property is defined in the FtpWebResponse
class, not in the WebResponse
parent class. That means the code must cast the generic WebResponse
returned by the GetReponse
method into its true identity: an FtpWebResponse
object.
Figure 20-3 shows the FtpGetFileInfo example program displaying information about a file on an anonymous FTP server.
Other FTP commands such as DeleteFile
, ListDirectory
, and ListDirectoryDetails
work more or less the same way; although, they return different results in their response streams.
The System.Net.Mail
namespace includes classes that let you send e-mail. The process is straightforward but somewhat cumbersome because there are a lot of options that can go along with an e-mail message. A message can have
Fortunately, these features are fairly easy to use. You simply create a MailMessage
object and set its properties to provide all the necessary information.
The SendEmail example program, which is available for download on this book’s website, uses the following SendEmailMessage
method to send a simple e-mail message.
// Send an email.
private void SendEmailMessage(string toName, string toEmail,
string fromName, string fromEmail,
string host, int port, bool enableSsl, string password,
string subject, string body)
{
// Make the mail message.
MailAddress fromAddress = new MailAddress(fromEmail, fromName);
MailAddress toAddress = new MailAddress(toEmail, toName);
MailMessage message = new MailMessage(fromAddress, toAddress);
message.Subject = subject;
message.Body = body;
// Get the SMTP client.
SmtpClient client = new SmtpClient()
{
Host = host,
Port = port,
EnableSsl = enableSsl,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, password),
};
// Send the message.
client.Send(message);
}
The method starts by creating two MailAddress
objects to represent the sender’s name and e-mail address and the recipient’s name and e-mail address. It then uses those objects to make a MailMessage
object representing an e-mail message from the sender to the recipient. The code finishes preparing the MailMessage
by setting its Subject
and Body
properties.
Next, the code creates an SmtpClient
object to send the message. It sets the object’s Host
and Port
properties to indicate the mail server that will process the message.
The code sets the SmtpClient
’s EnableSsl
property to enable or disable Secure Sockets Layer (SSL) to encrypt the connection with the host. The example program enables SSL.
To prevent an evildoer from using your e-mail account to send spam about Nigerian oil money to everyone in North America, you must use a NetworkCredential
object to log in to the mail server. The program creates this object using the sender’s e-mail address and the password entered on the example program’s form. Enter the password that you use to access your e-mail account.
Finally, when the SmtpClient
object knows all the details about how it should send the message, the code simply calls its Send
method, passing it the MailMessage
that it should send.
When you know how to write a program that sends e-mail, it’s not too hard to write one that sends SMS text messages. To send an SMS message, send an e-mail message to an e-mail address with the format number@gateway
where
number
is the recipient’s telephone number with no special characters such as -
, (
,)
, or +
.gateway
is the SMS e-mail gateway used by the recipient’s telephone carrier.
For example, the following e-mail address would send a text message to the phone number 1-234-567-8901 assuming that phone number’s carrier is Air Fire Mobile.
[email protected]The following web page contains a long list of telephone carriers and their SMS e-mail gateways.
https://github.com/cubiclesoft/email_sms_mms_gateways/blob/master/sms_mms_gateways.txt
Unfortunately, this method still requires you to know the recipient’s telephone carrier so that you can look up the SMS gateway address. (I don’t know how to learn the carrier automatically from just the phone number. If you figure it out, please e-mail me at [email protected]. For bonus points, write a program to e-mail me the information.)
As you do for any e-mail message, you need to include a mail host and port, and a sender e-mail address and password. The message body and subject define the message that the recipient receives. On my phone, a typical message might look like the following:
[email protected] / This is the subject / This is the message body.
The WebClient
class makes uploading and downloading files relatively simple. In situations in which the WebClient
class doesn’t give you enough control, you can use the WebRequest
and WebResponse
classes to move data to and from a network with streams.
The SmtpClient
, MailMessage
, and MailAddress
classes let you send e-mails quite easily. By sending a message to the proper e-mail address, you can send SMS text messages to a phone.
Together these classes provide some powerful tools for interacting with networks such as the Internet.
In addition to describing these classes, this chapter also defined a bunch of terms and abbreviations. The following table recaps those definitions.
TERm | Meaning |
datagram | A basic unit of data sent over a packet-switched network. Datagrams may arrive out of order. |
HTTP (HyperText Transfer Protocol) | A protocol that defines how messages are formatted and transmitted. It sits at a higher level than socket and datagram communications. |
URL (Uniform Resource Location) | An address that specifies where some resource is located. Typical web addresses that you open with a browser are URLs. |
URN (Uniform Resource Name) | A name that identifies something but doesn’t necessarily refer to a “physical” resource location. |
ISBN (International Standard Book Number) | A unique value that identifies a book. Because an ISBN does not tell you where to find a particular copy of the book, an ISBN is a URN but not a URL. |
URI (Uniform Resource Identifier) | Includes both URLs and URNs. |
TCP (Transmission Control Protocol) | One of the protocols used by the Internet that specifies how to move data from one point in the network to another. TCP provides reliable delivery of data in its correct order. TCP and IP are used together so frequently that they are often called TCP/IP. |
IP (Internet Protocol) | One of the protocols used by the Internet that specifies how to move data from one point in the network to another. IP ensures delivery of data based on an addressing scheme. TCP and IP are used together so frequently that they are often called TCP/IP. |
FTP (File Transfer Protocol) | Defines protocols for transferring files from one host to another on a TCP network such as the Internet. |
SMTP (Simple Mail Transfer Protocol) | An Internet protocol for transmitting e-mail messages across an IP (Internet Protocol) network. |
SSL (Secure Sockets Layer) | Encrypts communications between Internet locations such as between an e-mail client and an e-mail server. |
SMS (Short Message Service) | A service that uses standardized protocols to send text messages to phones. |
When your program sends e-mails or text messages, you might like to parse the addressing information to see if it makes sense. For example, you cannot send e-mail to the address this@is@[email protected] and you cannot send an SMS message to the phone number 1-111-111
.
Depending on the patterns you need to recognize, parsing values can be difficult. The following chapter describes regular expressions, a powerful tool you can use to make this sort of pattern recognition easier.
WebClient
’s DownloadFile
method to download the file http://www.csharphelper.com/howto_index.html and save it as the local file howto_index.html.WebClient
’s DownloadString
method to download the file http://blog.csharphelper.com/2010/07/02/draw-a-filled-chrysanthemum-curve-in-c.aspx. For bonus points, display it in a WebBrowser
control.
Hints: To display HTML text in a WebBrowser
control, first add the following code to the form’s Load
event handler to initialize the WebBrowser
.
webBrowser1.Navigate("about:blank");
Then use code similar to the following to display the HTML stored in the string variable html
in the control.
webBrowser1.Document.Body.InnerHtml = html;
DownloadStringAsync
example program (or write your own version) and modify it so that it uses the DownloadStringTaskAsync
method.
Hints: Use the following statement to start the download.
string result = await client.DownloadStringTaskAsync(uri);
You can still use a DownloadStringCompleted
event handler if you like, but you don’t need to because you can move its code right after the call to DownloadStringTaskAsync
(with a few error handling modifications).
await
in Exercise 3 is that it simplifies the code by allowing you to remove the DownloadStringCompleted
event handler. How large is the benefit in this case? How could you increase the benefit?WebClient
’s OpenStream
method to download an image file and display it in a PictureBox
. Test the program by downloading the file http://www.csharphelper.com/howto_filled_chrysanthemum_curve.png. (Hint: The Bitmap
class has a constructor that takes a stream as an argument.)DownloadStreamAsync
method. Allow the user to cancel the download, but remember that this method doesn’t fire the DownloadProgressChanged
event.WebClient
’s DownloadData
method to download an image file and display it in a PictureBox
. Test the program by downloading the file http://www.csharphelper.com/howto_filled_chrysanthemum_curve.png. (Hint: The MemoryStream
class has a constructor that takes a byte[]
as an argument.)WebRequest
class’s Http.Get
method to download and display an image file. Test the program on the file http://www.csharphelper.com/howto_vortex_fractal_smooth4.png
.WebClient
’s UploadFile
method to upload a file to a web server. (You need to provide your own server, username, and password.)WebClient
’s UploadString
method to upload a string into a file on a web server. (You need to provide your own server, username, and password.)WebRequest
class to upload a file to a web server. (You need to provide your own server, username, and password.) (Hint: Write an UploadBytesIntoFile
method that uploads a byte
array. Then write an UploadFile
method that reads a file into a byte
array and then calls UploadBytesIntoFile
to do the real work.)WebRequest
class to upload a string
to a web server. (You need to provide your own server, username, and password.) (Hint: Use the UploadBytesIntoFile
method you wrote for Exercise 11.)ListDirectory
FTP command to list the files in an FTP directory. (For testing, you can use the anonymous FTP directory ftp://nssdcftp.gsfc.nasa.gov/photo_gallery/hi-res/astro.)ListDirectoryDetails
FTP command.MailAddress
object to the MailMessage
object’s CC
collection.)Note that some mail servers are clever enough to combine multiple copies of the same message sent to the same recipient. In this exercise, for example, if you use your own e-mail address as both the recipient and the CC recipient, your mail server may combine the two copies and you’ll receive only one of them.
To test your solution, use my e-mail address [email protected] for one of the addresses. I’ll send you a reply saying I got it. (Please try to send me only one message when you have the program debugged. Don’t spam me with dozens of messages while you’re working on early versions of the program.)
MailMessage
’s Bcc
collection.)