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.
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.
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.
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.
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.
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() | ||
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. |
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 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.
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");
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.
The WebClient class has various properties that can be used to configure the request and get information about the response.
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.
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.
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");
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 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.
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.
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
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. |
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);
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.
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. |
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.
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.
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. |
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. |
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.
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
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. |
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. |
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.
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.
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.
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 |
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);