In the following sections, you will connect to a server, first by hand and with telnet, and then with a Java program.
1. Using Telnet
The telnet program is a great debugging tool for network programming. You should be able to launch it by typing telnet from a command shell.
You may have used telnet to connect to a remote computer, but you can use it to communicate with other services provided by Internet hosts as well. Here is an example of what you can do. Type
telnet time-a.nist.gov 13
As Figure 4.1 shows, you should get back a line like this:
57488 16-04-10 04:23:00 50 0 0 610.5 UTC(NIST) *
What is going on? You have connected to the “time of day” service that most UNIX machines constantly run. The particular server that you connected to is operated by the National Institute of Standards and Technology and gives the measurement of a Cesium atomic clock. (Of course, the reported time is not completely accurate due to network delays.)
By convention, the “time of day” service is always attached to “port” number 13.
The server software is continuously running on the remote machine, waiting for any network traffic that wants to chat with port 13. When the operating system on the remote computer receives a network package that contains a request to connect to port number 13, it wakes up the listening server process and establishes the connection. The connection stays up until it is terminated by one of the parties.
When you began the telnet session with time-a.nist.gov at port 13, a piece of network software knew enough to convert the string “time-a.nist.gov” to its correct Internet Protocol (IP) address, 188.8.131.52. The telnet software then sent a connection request to that address, asking for a connection to port 13. Once the connection was established, the remote program sent back a line of data and closed the connection. In general, of course, clients and servers engage in a more extensive dialog before one or the other closes the connection.
Here is another experiment along the same lines—but a bit more interesting. Type
telnet horstmann.com 80
Then type very carefully the following:
GET / HTTP/1.1
That is, hit the Enter key twice at the end.
Figure 4.3 shows the response. It should look eerily familiar—you got a page of HTML-formatted text, namely Cay Horstmann’s home page.
This is exactly the same process that your web browser goes through to get a web page. It uses HTTP to request web pages from servers. Of course, the browser displays the HTML code more nicely.
2. Connecting to a Server with Java
Our first network program in Listing 4.1 will do the same thing we did using telnet—connect to a port and print out what it finds.
The key statements of this simple program are these:
var s = new Socket(“time-a.nist.gov”, 13);
InputStream inStream = s.getInputStream();
The first line opens a socket, which is a network software abstraction that enables communication out of and into this program. We pass the remote address and the port number to the socket constructor. If the connection fails, an UnknownHostException is thrown. If there is another problem, an IOException occurs. Since UnknownHostException is a subclass of IOException and this is a sample program, we just catch the superclass.
Once the socket is open, the getInputStream method in java.net.Socket returns an InputStream object that you can use just like any other stream. Once you have grabbed the stream, this program simply prints each input line to standard output. This process continues until the stream is finished and the server disconnects.
This program works only with very simple servers, such as a “time of day” service. In more complex networking programs, the client sends request data to the server, and the server might not immediately disconnect at the end of a response. You will see how to implement that behavior in several examples throughout this chapter.
The Socket class is pleasant and easy to use because the Java library hides the complexities of establishing a networking connection and sending data across it. The java.net package essentially gives you the same programming interface you would use to work with a file.
3. Socket Timeouts
Reading from a socket blocks until data are available. If the host is unreachable, your application waits for a long time and you are at the mercy of the underlying operating system to eventually time out.
You can decide what timeout value is reasonable for your particular application. Then, call the setSoTimeout method to set a timeout value (in milliseconds).
var s = new Socket(. . .);
s.setSoTimeout(10000); // time out after 10 seconds
If the timeout value has been set for a socket, all subsequent read operations throw a SocketTimeoutException when the timeout has been reached before the operation has completed its work. You can catch that exception and react to the timeout.
InputStream in = s.getInputStream(); // read from in
catch (SocketTimeoutException e)
react to timeout
There is no timeout for write operations.
There is one additional timeout issue that you need to address. The constructor
Socket(String host, int port)
can block indefinitely until an initial connection to the host is established.
You can overcome this problem by first constructing an unconnected socket and then connecting it with a timeout:
var s = new Socket();
s.connect(new InetSocketAddress(host, port), timeout);
See Section 4.2.4, “Interruptible Sockets,” on p. 244 for how to allow users to interrupt a socket connection at any time.
4. Internet Addresses
Usually, you don’t have to worry too much about Internet addresses—the numerical host addresses that consist of 4 bytes (or, with IPv6, 16 bytes) such as 184.108.40.206. However, you can use the InetAddress class if you need to convert between host names and Internet addresses.
The java.net package supports IPv6 Internet addresses, provided the host operating system does.
The static getByName method returns an InetAddress object of a host. For example,
InetAddress address = InetAddress.getByName(“time-a.nist.gov”);
returns an InetAddress object that encapsulates the sequence of four bytes 220.127.116.11. You can access the bytes with the getAddress method.
byte addressBytes = address.getAddress();
Some host names with a lot of traffic correspond to multiple Internet addresses, to facilitate load balancing. For example, at the time of this writing, the host name googte.com corresponds to twelve different Internet addresses. One of them is picked at random when the host is accessed. You can get all hosts with the getAttByName method.
InetAddress addresses = InetAddress.getAttByName(host);
Finally, you sometimes need the address of the local host. If you simply ask for the address of tocathost, you always get the local loopback address 127.0.0.1, which cannot be used by others to connect to your computer. Instead, use the static getLocatHost method to get the address of your local host.
InetAddress address = InetAddress.getLocatHost();
Listing 4.2 is a simple program that prints the Internet address of your local host if you do not specify any command-line parameters, or all Internet addresses of another host if you specify the host name on the command line, such as
java inetAddress/InetAddressTest www.horstmann.com
Listing 4.2 inetAddress/InetAddressTest.java
Source: Horstmann Cay S. (2019), Core Java. Volume II – Advanced Features, Pearson; 11th edition.