Chapter 14. Networking

This chapter covers the Microsoft .NET Framework networking classes, showing how they work and where there are differences from the java.net package. Table 14-1 shows the tiers of service provided by the classes in the java.net package alongside their .NET equivalents.

Table 14-1. Three Network Tiers of Service

Service Tier

Java

.NET

Request/response

URLConnection

System.Net.WebClient

  

System.Net.WebRequest

  

System.Net.WebResponse

Protocol

Socket

System.Net.Sockets.TcpClient

 

ServerSocket

System.Net.Sockets.TcpListener

 

DatagramSocket

System.Net.Sockets.UdpClient

 

MulticastSocket

 

Native socket access

N/A

System.Net.Sockets.Socket

The first section of this chapter discusses the WebClient, WebRequest, and WebResponse classes that support the request/response tier. The request/response tier supports HTTP-type requests, whereby a client initiates a connection, sends a message to the server, and blocks until the server returns a response via the open connection.

The protocol tier exposes more control to the programmer and can be used for streams-based programming. The programmer can develop custom clients and servers and can send and receive both point-to-point and broadcast messages. The protocol tier consists of a set of convenience classes that make using underlying sockets easier; these classes are discussed in the second part of the chapter.

Finally, the .NET Framework provides a managed code wrapper around the WinSock32 sockets API and provides the programmer with fine-grain control of networking, albeit at the cost of additional complexity. The native socket classes are discussed in the final part of this chapter.

Accessing the Internet

This section discusses the classes that make it possible to make Internet requests. We cover the underlying classes that deal with host names, network addresses, Uniform Resource Identifiers (URIs), and Uniform Resource Locators (URLs), and we conclude this section with the different ways that Internet requests can be handled.

URLs and URIs

Java version 1.4 includes the new java.net.URI class. This class coexists alongside java.net.URL, but the URL class doesn’t inherit from the URI class. The .NET Framework includes the System.Uri class, which is an overarching representation of all URIs and therefore URLs.

Java and .NET both use pluggable protocol handlers to abstract URLs from the network protocol implementations. A protocol handler is a class that can service requests for one or more URI schemes. These handlers are registered with a factory class that will create instances in response to calls to a static method ensuring that new types of URI support can be added in the future. The .NET Framework includes protocol handlers for the http, https, and file schemes.

Note

Unlike java.net.URLConnection, the .NET Framework classes do not provide support for the ftp protocol.

The contents of a System.Uri instance are immutable. To manipulate URI strings, the programmer must use the System.UriBuilder class, which allows the segments of the URI string to be changed.

Constructors

The Java URL class contains overloaded constructors that support the specification of individual elements of a URL. The .NET Uri class is constructed using strings that are parsed into individual elements and can take arguments representing a base URL and the resource name to target.

This example demonstrates how to create instances of the Uri class:

Uri x_uri1 = new Uri("http://www.microsoft.com/ms.htm");
Uri x_base = new Uri("http://www.microsoft.com");
Uri x_uri2 = new Uri(x_base, "ms.htm");

The Uri class also provides constructors that allow the programmer to specify whether escape characters should be substituted in the URL. Here’s an example of creating a new URI using a string that is already escaped:

Uri x_uri = new Uri("http://www.microsoft.com/
Hello%20World.htm", true);

Setting the second argument to true indicates that the string should not be escaped, preventing the Uri string from being escaped twice, which would cause the percentage symbol to be mapped out of the string.

Methods

Table 14-2 contrasts the java.net.URI and java.net.URL classes against the .NET System.Uri class.

Table 14-2. Comparison Between the Java URI and URL Classes and the .Net Uri Class

java.net.URI & java.net.URL

System.Uri

Comments

URI.create(String)

new Uri(string)

Parses the string argument to create a new Uri.

URI.getAuthority()

Authority

Gets the authority for the URI. The authority is the fully qualified host name or Domain Name System (DNS) address of the server plus the port number if the port is not the default for the scheme.

URL.getAuthority()

  

URL.getContent()

N/A

 

URL.getContent(Class[])

  

URI.getFragment()

Fragment

System.Uri does not include the fragment in equality checks.

URI.getHost()

Host

 

URL.getHost()

  

N/A

HostNameType

Returns the type of host name specified in the URI—for example, a DNS name or an IP address. Both versions 4 and 6 are supported.

URI.getPath()

AbsolutePath

 

URL.getPath()

  

URI.getQuery()

Query

 

URL.getQuery()

  

N/A

PathAndQuery

Gets the AbsolutePath and Query properties, separated by a question mark.

URI.getPort()

Port

 

URL.getPort()

  

URL.getDefaultPort()

N/A

 

N/A

IsDefaultPort

Returns true if the port is the default for the URI scheme.

URI.getScheme()

Scheme

 

URL.getProtocol()

  

N/A

IsFile

Returns true if the URI references a file.

N/A

IsLoopback

Returns true if the URI references the local host.

N/A

IsUNC

Returns true if the URI is a UNC path (\serverfolderfile).

URI.getUserInfo()

UserInfo

 

URI.isAbsolute()

N/A

 

URI.isOpaque()

N/A

 

URI.normalize()

N/A

 

URL.openConnection()

N/A

See The WebClient Class section coming up for information on the WebClient class.

URL.openStream()

  

URI.parseServerAuthority()

N/A

 

URI.relativize(URI)

MakeRelative(Uri)

 

URI.resolve(URI)

new Uri(Uri, string)

 

URI.toURL()

N/A

The .NET Framework doesn’t provide a separate class representation for URLs.

N/A

Segments

Returns a String array containing all of the elements that make up the URI.

N/A

CheckHostName (string)

Checks a host name to ensure that it is valid. The name is not resolved but simply checked to ensure that it meets the requirements for validity.

N/A

CheckSchemeName (string)

Checks a URI scheme name for compliance with RFC 2396.

The WebClient Class

The easiest way to perform Web requests is with the System.Net.WebClient class. This class provides functionality similar to that of the Java URLConnection class for sending and receiving data. WebClient supports requests to URIs using the https, http, and file schemes.

The WebClient class provides a simplified networking model that is easy to use and sufficient for many purposes. However, the cost of this simplicity is a loss of functionality and flexibility. For example, with HTTP requests, WebClient doesn’t support cookies or credentials, doesn’t provide access to the result code sent back by the server, and will throw an exception if the code isn’t OK, which is indicated by result code 200.

Downloading Data

The following example shows the Java URLConnection class used to download the Microsoft home page writing the content to the console:

URLConnection x_connection
    = new URL("http://www.microsoft.com").openConnection();

BufferedReader x_reader = new BufferedReader(
    new InputStreamReader(x_connection.getInputStream()));
String x_str;
while ((x_str = x_reader.readLine()) != null) {
    System.out.println(x_str);
}
x_reader.close();

Here’s a C# implementation using the .NET WebClient class:

WebClient x_client = new WebClient();

StreamReader x_reader =
     new StreamReader(x_client.OpenRead("http://www.microsoft.com"));
string x_str;
while ((x_str = x_reader.ReadLine()) != null) {
    Console.WriteLine(x_str);
}
x_reader.Close();

The two approaches are similar, hiding the complexities of the underlying network protocols and providing the programmer with a stream containing the results of the download request. The key difference with WebClient is that the target URI is passed as an argument to the OpenRead method, not the constructor as with URLConnection, allowing WebClient instances to be reused across multiple URIs.

The WebClient class also provides two convenience methods for downloading data into byte arrays and directly into local files. To download data into a byte array, use the DownloadData method, as in the following example:

WebClient x_client = new WebClient();
byte[] x_data = x_client.DownloadData("http://www.microsoft.com");

To download data and store it directly in a local file, use the DownloadFile method. The following example downloads the Microsoft home page and stores it in homepage.html:

WebClient x_client = new WebClient();
x_client.DownloadFile("http://www.microsoft.com", "homepage.html");

Uploading Data

Sending data to a server with the WebClient is similar to receiving data. Four methods can be used; they are listed in Table 14-3.

Table 14-3. The WebClient Methods Used to Send Data to a Server

Method

Description

OpenWrite()

Returns a stream that can be used to write data to the server

UploadData()

Writes a byte array to the server and returns a byte array representing the response

UploadFile()

Uploads the contents of a specified file and returns a byte array representing the server response

UploadValues()

Uploads a series of name/value pairs

Each of these four methods is overloaded to accept an HTTP method argument. The default method is POST, but any method can be used. Note that the value of the HTTP method isn’t validated against values allowed by the HTTP specification.

Configuring WebClient

The WebClient class has various properties that can be used to configure the request and get information about the response.

Request headers

By default, all requests contain the following headers:

  • Connection: Keep-Alive

  • Host: <name of host derived from the URL used to create the request>

Requests to send data to the server also contain the following headers:

  • Content-Length: <length of data being sent>

  • Expect: 100-continue

Headers can be set through the Headers property, specifying key/value pairs through an indexer. The default headers just listed don’t appear in the WebHeaderCollection that the property returns. WebHeaderCollection is derived from System.Collections.Specialized.NameObjectCollectionBase. For more information, see Chapter 9.

Setting a header for an instance of WebClient affects all subsequent requests to the server. If requests to the same server require different headers, different instances of WebClient should be used, or the headers should be modified between requests.

Response headers

After each call to send or receive data, the ResponseHeaders property will return a WebHeaderCollection that contains name/value pairs for each of the headers contained in the response. The response headers reflect the result of the most recent request and are overwritten with each subsequent request.

Setting a base address

The WebClient class allows a base address to be set. The request strings passed to the upload and download methods will be appended to the base address to form fully qualified URLs. If passed a fully formed request string, the WebClient base address is not used but remains in place for future requests.

The following example demonstrates the use of the BaseAddress property. First the base address is set to http://www.microsoft.com. A subsequent DownloadData call specifying ms.htm results in a call to the URI http://www.microsoft.com/ms.htm:

WebClient x_client = new WebClient();
x_client.BaseAddress = "http://www.microsoft.com";
byte[] x_data = x_client.DownloadData("ms.htm");

WebRequest and WebResponse

The WebRequest and WebResponse classes represent the next level down in the network class hierarchy, placing the programmer closer to the protocol implementation. The main advantage of using the WebRequest and WebResponse classes over the WebClient class is the level of control available to the programmer. Instances of these abstract types can be cast to protocol-specific concrete types, taking advantage of the methods and properties that expose more control over the request. For example, the WebResponse class can be cast to HttpWebResponse, which supports features such as cookies and protocol versions.

Here’s a simple example using the WebRequest and WebResponse classes to write the contents of the Microsoft homepage to the console:

WebRequest x_req = WebRequest.Create("http://www.microsoft.com");
WebResponse x_response = x_req.GetResponse();
StreamReader x_reader
    = new StreamReader(x_response.GetResponseStream());
String x_str;
while ((x_str = x_reader.ReadLine()) != null) {
    Console.WriteLine(x_str);
}
x_reader.Close();

WebRequest

WebRequest is an abstract class that encapsulates functionality common to all Internet requests. Implementation classes that represent a specific protocol are not required to deal with all of the features, so many of the properties in the class can throw a System.NotSupportedException to indicate that the feature has no meaning for the protocol that will be used to handle the request.

Creating a request

Instances of WebRequest are created using the static WebRequest.Create factory method. The Create method takes either a System.Uri or a String containing a URI that specifies the destination of the request.

The factory method approach enables the Create method to return a subclass of WebRequest designed to handle the protocol specified in the URI argument. Currently only two protocol-specific handlers are provided, HttpWebRequest for http and https scheme requests and FileWebRequest for file scheme requests.

Configuring a request

Table 14-4 lists the properties of the WebRequest class. Not all of these properties apply to all protocol implementations, and many of the following items are clearly derived from an HTTP-centric view of Internet requests.

Table 14-4. The WebRequest Properties

Property

Description

ContentType

Gets or sets the type of content being sent to the server.

ConnectionName

Sets a name for the connection. Connections with different names will use a different ServicePoint, discussed in the HTTP Connection Features section later in this chapter.

Credentials

Gets or sets the security credentials that will be used in the request. See the Request Credentials section coming up for more information.

Headers

Gets or sets the collection of name/value pairs that will be used as the headers for the request.

Method

Gets or sets the protocol method to use in the request.

PreAuthenticate

Specifies whether the available authentication information should always be sent with the request or only in response to an authorization challenge.

Proxy

Gets or sets the System.Net.IWebProxy that will be used for the request.

RequestUri

Returns the URI of the request.

Timeout

Gets or sets the amount of time that will elapse before the request times out.

Setting Proxies

The default proxy for all WebRequest instances is configured using the System.Net.GlobalProxySelection class. The WebRequest.Proxy property enables the proxy to be set on a per-request basis, overriding the global default. The following example demonstrates the setting of a default proxy:

Uri x_uri = new Uri("http://myproxy:8080");
GlobalProxySelection.Select = new WebProxy(x_uri);

Request Credentials

The System.Net.CredentialCache class stores credentials used to access Internet resources, typically applied to HTTP requests. A single cache of credentials supports authentication information for multiple Internet resources but is intended for supporting a single user. Here is an example of defining credentials:

CredentialCache x_cache = new CredentialCache();
x_cache.Add(new Uri("http://www.microsoft.com"), "Basic",
    new NetworkCredential("adam", "adams_password"));
x_cache.Add(new Uri("http://www.java.sun.com"), "Digest",
    new NetworkCredential("adam", "adams_other_password"));

The code fragment defines two different credentials, both of which are associated with the user adam. Although account names may differ from system to system, the CredentialCache class is not intended to track different users. Credentials are associated with a request using the Credentials property, and the PreAuthenticate property controls whether the credentials are always set with a request or only in response to an authorization challenge. The WebRequest class and the concrete implementations are responsible for determining the best credential to use from the cache.

WebResponse

Instances of WebResponse cannot be instantiated directly but are obtained when the WebRequest.GetResponse method is called. Calling GetResponse causes the WebRequest instance to send the request to the server; nothing is sent across the network until GetResponse is invoked.

As with WebRequest, WebResponse provides an abstract view of a server response and does not expose protocol-specific functionality. For protocol-specific functionality, cast the WebResponse instance to an HttpWebResponse or a FileWebResponse. Table 14-5 lists the properties available in the WebResponse class.

Table 14-5. The WebResponse Properties

Property

Description

ContentLength

Gets the content length of the data returned from the server, excluding any headers.

ContentType

Gets the Multipurpose Internet Mail Extensions (MIME) content type of the data returned from the server.

Headers

Gets a collection of name/value pairs that represent the headers returned by the server.

ResponseUri

Gets the URI of the server that responded to the request.

Getting response data

WebResponse defines the GetResponseStream method, which returns a stream that is used to read the content returned by the server. See the example at the start of this section for a demonstration of reading content with the response stream.

Protocol-Specific Request and Response Classes

Two sets of protocol implementation classes are available in the .NET Framework. The HttpWebRequest and HttpWebResponse classes are responsible for the http and https URI schemes, while FileWebRequest and FileWebResponse are responsible for the file scheme.

These protocol-specific classes aren’t available for direct instantiation. The static Create and instance GetResponse methods in the WebRequest class always return one of the abstract base classes. If the programmer requires more specific access, the types returned from these methods can be cast to the appropriate protocol-handler class.

File protocol classes

The FileWebRequest and FileWebResponse classes service requests for the file scheme. These classes don’t expose any additional information about the file that matches the request, and there is little value in casting to these types when using the request/response classes.

HTTP protocol classes

The HttpWebRequest and HttpWebResponse classes are responsible for servicing requests using the HTTP and SSL/TLS protocols, represented by the http and https URI schemes. The classes extend the abstract WebRequest and WebResponse classes to expose features that are specific to the HTTP protocols and provide a lot of the functionality that is available in the java.net.URLConnection class. These classes provide many HTTP-specific features, including the following:

  • Selecting between versions 1.0 and 1.1 of the HTTP protocol

  • Setting HTTP request headers

  • Managing cookies

  • Configuring connection persistence and request pipelining

  • Support for automatically following redirection directives

Here’s the example we used at the start of this section for downloading the Microsoft home page. This time we cast the request and response to the HTTP protocol classes:

HttpWebRequest x_req =
    (HttpWebRequest)WebRequest.Create("http://www.microsoft.com");
HttpWebResponse x_response = (HttpWebResponse)x_req.GetResponse();
StreamReader x_reader =
    new StreamReader(x_response.GetResponseStream());
String x_str;
while ((x_str = x_reader.ReadLine()) != null) {
    Console.WriteLine(x_str);
}
x_reader.Close();

Table 14-6 details the members of the HttpWebRequest and HttpWebResponse classes.

Table 14-6. Members of the HttpWebRequest and HttpWebResponse Classes

Property/Method

Description

Accept

Represents the value of the Accept HTTP header.

AddRange()

Adds an HTTP Range header to the request.

Address

Gets the URI of the server that responded to the request. The HTTP request and response classes will follow redirection instructions. This property returns the URI of the server after redirections have been performed. The ResponseUri property in the base class does not take into account redirections.

AllowAutoRedirect

If set to true, redirection directives issued by servers will be followed automatically. If set to false, a redirection message is considered to be a response.

AllowWriteStreamingBuffer

If set to true, write operations to the server will be buffered in memory. This is useful when redirection directives are received and AllowAutoRedirect is enabled.

Connection

Represents the value of the Connection HTTP header.

ContinueDelegate

Allows a delegate to be set that will be executed when a server returns an HTTP Continue response.

CookieContainer

Represents the cookies associated with the request.

Expect

Represents the value of the HTTP Expect header.

HaveResponse

Returns true if the server has returned a response to the request.

IfModifiedSince

Represents the value of the HTTP If-Modified-Since header.

KeepAlive

Used to determine whether a connection to a server should be persistent, via the Connection: KeepAlive header.

MaximumAutomaticRedirections

Specifies the number of redirection directives that will be followed when AllowAutoRedirect is enabled. Defaults to 50 redirections.

Pipelined

When true, indicates that connections should be pipelined in accordance with version 1.1 of the HTTP protocol, whereby multiple requests and responses are handled in series over a single connection.

ProtocolVersion

Sets the version of HTTP that will be used in the request. Versions 1.0 and 1.1 are supported.

Referer

Represents the value of the Referer HTTP header.

SendChunked

When true, data will be sent to the server encoded in chunked segments.

ServicePoint

See the HTTP Connection Features section coming up for information about service points.

TransferEncoding

Represents the value of the Transfer-encoding HTTP header.

UserAgent

Represents the value of the User-agent HTTP header.

HTTP Connection Features

The .NET Framework provides support for controlling the number of open network connections to each HTTP server. Large numbers of connections have a performance impact at both the server and the client. The connection persistence and request pipelining features of the HTTP protocol are used to allow a small number of open connections to service a large number of requests.

This support is provided by the System.Net.ServicePoint class, which applies a basic set of constraints for each remote server that an application is using. A new ServicePoint instance is instantiated when a request to a new server is created, applying the default limits contained in the System.Net.ServicePointManager class.

The ServicePoint class has an idle time limit. If no requests are made to the server associated with the service point within this limit, the instance is freed and is available for garbage collection. While an instance of ServicePoint is valid, all connections to the server will be governed by the service point settings.

When a ServicePoint times out, any settings that are different from the defaults in ServicePointManager will be lost. It isn’t possible to create an instance of ServicePoint and manually associate it with an HTTP request. To ensure that a host retains specific settings, the ServicePoint instance needs to be manually configured for each request.

Setting Defaults for All Hosts

The ServicePointManager class manages a collection of ServicePoint instances. This class is responsible for creating new ServicePoint instances as required and applying default values. Changes to the defaults are not applied to previously created ServicePoint instances.

Table 14-7 lists the features defined in the ServicePointManager class.

Table 14-7. The ServicePointManager Class

Method/Property

Description

DefaultNonPersistentConnectionLimit

The default number of concurrent connections allowed to an HTTP/1.0 server, currently set to 4.

DefaultPersistentConnectionLimit

The default number of concurrent connections allowed to an HTTP/1.1 server, currently set to 2.

DefaultConnectionLimit

Gets or sets the default number of connections that will be set for new instances of ServicePoint.

MaxServicePointIdleTime

Specifies the number of milliseconds that a ServicePoint can remain disconnected from the server before being considered expired.

MaxServicePoints

The maximum number of ServicePoint instances allowed. The default value (0) indicates that there is no limit. Setting a limit will cause an exception to be thrown if the limit is exceeded by requests to new servers.

FindServicePoint()

Returns the ServicePoint associated with a URI. New instances will be created as required.

Configuring a Specific Host

Instances of ServicePoint aren’t created until the GetResponse method is called in the HttpWebRequest class or until the FindServicePoint method is used for a server that has not previously been contacted.

The first method of configuring the settings for a host is to ensure that the service point is created before any requests are made. Here’s an example:

Uri x_uri = new Uri("http://www.microsoft.com");
ServicePoint x_sp = ServicePointManager.FindServicePoint(x_uri);
x_sp.ConnectionLimit = 10;

WebRequest x_req = WebRequest.Create(x_uri);
WebResponse x_resp = x_req.GetResponse();

In this code fragment, we call the FindServicePoint method before we make any requests to the HTTP server and change the limit for concurrent connections. Since no calls have yet been made to the URI, a new instance will be created. When we call the GetResponse method in the WebRequest class, the ServicePoint we have configured will be located and used.

The second approach involves making an initial connection and configuring the ServicePoint that is automatically created when the GetResponse method is called. Here’s an example:

Uri x_uri = new Uri("http://www.microsoft.com");
WebRequest x_req = WebRequest.Create(x_uri);
WebResponse x_resp = x_req.GetResponse();

ServicePoint x_sp = ((HttpWebRequest)x_req).ServicePoint;
x_sp.ConnectionLimit = 10;

For the first request, the ServicePointManager default values will be applied. Subsequent requests will be subject to the configured values.

ServicePoint instances will be released for garbage collection if a connection isn’t made to the server within the time limit. Subsequent connections will result in a new ServicePoint being created with the defaults from ServicePointManager. We recommend changing the default values where possible to avoid incorrect settings being accidentally applied.

Table 14-8 lists the methods and properties defined in the ServicePoint class.

Table 14-8. The ServicePoint Class

Method/Property

Description

Address

Gets the URI of the server that the ServicePoint connects to.

ConnectionLimit

The maximum number of concurrent connections that will be allowed to the server. This defaults to the ServicePointManager property DefaultConnectionLimit when the instance is created.

ConnectionName

Gets the connection name set by the WebRequest that caused the ServicePoint to be created. Only WebRequest objects with the same name can use a single ServicePoint.

CurrentConnections

Gets the number of connections open to the server.

IdleSince

Gets the date and time that the ServicePoint was last used. Any ServicePoint objects that are unused for longer than MaxIdleTime are released for garbage collection.

ProtocolVersion

Gets the version of HTTP used to communicate with the server. This is set automatically based on the response from the server.

SupportsPipelining

Indicates whether requests will be pipelined over a connection. This is set automatically based on the response from the server.

Names and Addresses

Most of the time, it’s sufficient to rely on the default behavior of the networking classes to correctly resolve host names to IP addresses. However, there are times when the developer needs to work directly with IP addresses and host names. Both Java and the .NET Framework provide support for creating and managing classes that represent IP addresses and support for resolving details directly using DNS.

Java takes the approach of bundling the support for IP addresses and resolving names into one class, java.net.InetAddress. With version 1.4, Java adds support for version 6 of the IP protocol (IPv6) and provides two derived classes, Inet4Address and Inet6Address, representing addresses for versions 4 and 6 of IP. The .NET Framework breaks out the functionality into several classes, representing conceptual elements for handling names and addresses. There is also a special class, System.Net.EndPoint, that represents a network resource or service.

Using the Domain Name System

The Java support for DNS is contained in the InetAddress class, and all methods to resolve host information return an instance of InetAddress. The .NET Framework includes the System.Net.Dns class, which is responsible for resolving names and addresses; the methods of the Dns class return the System.Net.IPHostEntry type, which represents a DNS record. Table 14-9 summarizes the IPHostEntry class.

Table 14-9. The IPHostEntry Class

Method/Property

Description

HostName

The primary name of a host

Aliases

A String array representing any aliases associated with the host

AddressList

An array of the IPAddress type associated with the host

The use of the IPHostEntry class to represent all of the DNS entry details available for a host provides a clean class structure. The Java InetAddress class provides methods that will return either one IP address or all addresses, while the .NET Dns class requires less complexity to achieve the same goals. The IPHostEntry type always contains all of the DNS information available.

Note

The Java support for name resolution caches successful results indefinitely. Changes in DNS records will not be reflected during the life of an application. The .NET DNS support is hooked directly into the Windows operating system and will reflect changes as they propagate down the DNS hierarchy, subject to the operating system settings.

Here is an example of resolving the name www.microsoft.com. The methods of the System.Net.Dns class are listed later in this section.

IPHostEntry x_entry = Dns.GetHostByName("www.microsoft.com");
Console.WriteLine("Host name: " + x_entry.HostName);
foreach (string x_str in x_entry.Aliases) {
    Console.WriteLine("Alias: " + x_str);
}
foreach (IPAddress x_addr in x_entry.AddressList) {
    Console.WriteLine("IP Address: " + x_addr.ToString());
}

The result of this fragment is shown here. Note that the results may change because a large number of servers host the Microsoft site.

Host name: www.microsoft.akadns.net
Alias: www.microsoft.com
IP Address: 207.46.230.219
IP Address: 207.46.197.100
IP Address: 207.46.197.102
IP Address: 207.46.230.218
IP Address: 207.46.197.113
IP Address: 207.46.230.220

We like this approach. We feel that the model of always getting all of the available information is cleaner and simpler, and the .NET classes expose more details from DNS than Java.

Table 14-10 shows the mapping between DNS support in the Java InetAddress and .NET Dns classes.

Table 14-10. The Mapping Between the Java InetAddress Class and the .NET Dns Class

java.net.InetAddress

System.Net.Dns

getByName()

GetHostByName()

getAllByName()

 

getByAddress()

GetHostByAddress()

getAllByAddress()

 

getLocalHost()

GetHostName()

IP Addresses

The main purpose of java.net.InetAddress is to represent an instance of an Internet Protocol address, and the additions for DNS resolution are a bolt-on feature. The .NET Framework relies on the System.Net.IPAddress class to do the same thing. Table 14-11 shows the mapping between these two classes.

Table 14-11. The Mapping Between the Java InetAddress Class and the .NET IPAddress Class

java.net.InetAddress

System.Net.IPAddress

Comments

getAddress()

Address

The IPAddress type returns a long instead of a byte array

getHostAddress()

ToString()

 

getHostName()

Dns.getHostByAddress(IPAddress).HostName

 

N/A

Parse()

Parses a String representing an IP address into an instance of IPAddress

N/A

IsLoopback()

Indicates whether an IPAddress is the loop-back address

Application Endpoints

The final class in this discussion is System.Net.IPEndPoint. This class represents a combination of a host address and port that can be used to contact a service on a remote computer. This class is used extensively with the lower-level networking classes discussed in Programming with Native Sockets later in this chapter. Instances of IPEndPoint are created using an IPAddress to represent the host and an integer to represent the port number, as follows:

IPAddress x_addr = IPAddress.Parse("207.46.230.219");
IPEndPoint x_endpoint = new IPEndPoint(x_addr, 80);

The example demonstrates how to parse a String into an instance of an IP address and then create the IPEndPoint. The address we used is from the list registered for www.microsoft.com, so this IPEndPoint represents the default port for HTTP on the Microsoft Web server. The same result can be achieved directly by using the results of a DNS lookup, as shown here:

IPHostEntry x_hostentry = Dns.GetHostByName("www.microsoft.com");
IPAddress x_addr = x_hostentry.AddressList[0];
IPEndPoint x_endpoint = new IPEndPoint(x_addr, 80);
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset