Reading and writing to a socket (a simple client)

22 Apr

Reading and writing to a socket (a simple client)

The following program is a very simple HTTP client. Given an Internet address such as www.java.sun.com and a web page such as index.html, it initiates a socket com- munication to the well-known port 80 (HTTP services) and requests a web page. The web page is printed to the screen in raw HTML format.

Listing 3-15: HttpSocketClient.java
import java.net.*;
import java.io.*;
public class HttpSocketClient {
public static void main(String[] args) {
try {
InetAddress addr = InetAddress.getByName(args[0]);
Socket webSocket = new Socket(addr, 80);
BufferedWriter clientRequest = new BufferedWriter(
new  OutputStreamWriter(webSocket.getOutputStream()));
BufferedReader serverResponse = new BufferedReader(
new  InputStreamReader(webSocket.getInputStream()));
clientRequest.write(“GET /” + args[1] + “ HTTP/1.1\n”);
clientRequest.write(“Host: “ + args[0] + “:80\n\n”);
clientRequest.flush();
while(serverResponse.readLine() != null) {
System.out.println(serverResponse.readLine());
}
} catch(Exception e){e.printStackTrace();}
}
}

The program consists of only one method, main(), that takes two string arguments: an Internet domain name and a web page. We take the first of those arguments, the domain name, and pass it to the InetAddress constructor, creating an InetAddress object called addr. The getByName() method will accept a host name or an IP address. This is one way of passing host information to the Socket constructor. There are eight versions of the Socket constructor, taking different types of arguments. We could have passed the domain name string args[0] directly to the constructor without having first gone through the process of creating the InetAddress. But this way gave us a context to show one more networking related class, InetAddress. The InetAddress object addr is passed to the socket constructor along with the port number, 80. This means we will be trying to contact the service running at port 80 on the host machine we specify. Port 80 corresponds to the predefined service of web browsing using HTTP. Locally, our Socket object webSocket, is not open on port 80. Java is choosing, at random, an unused port, above 1023. The socket address, made up of our host machine and the client port number, is passed to the server during this socket creation.

public class HttpSocketClient {
public static void main(String[] args) {
try {
InetAddress addr = InetAddress.getByName(args[0]);
Socket webSocket = new Socket(addr, 80);

Having created a Socket object called webSocket, we are going to use two of its methods to establish IO streams to the socket. It’s a good idea to use a buffered stream, so for writing to the socket, we will use a BufferedWriter stream. Its constructor needs to be given an OutputStreamWriter as an argument, so we need to create an OuputStreamWriter. The OutputStreamWriter constructor takes an OutputStream as its argument, so we need to get an OutputStream. The getOutputStream() method of the Socket library will provide that output stream. Instead of declaring named objects for the OutputStream and the OutputStreamWriter, we just use their creation as arguments to the required constructor and cascade them all together. This avoids a lot of naming objects that will never be referred to again. To read from the socket, we use an InputStreamReader. Its creation follows a similar process as the OutputStreamWriter. We now have an InputStreamReader, serverResponse, that corresponds to what we are reading from the socket and we have an OutputStreamWriter, clientRequest, that corresponds to what we are sending to the socket.

BufferedWriter clientRequest = new BufferedWriter(
new  OutputStreamWriter(webSocket.getOutputStream()));
BufferedReader serverResponse = new BufferedReader(
new  InputStreamReader(webSocket.getInputStream()));

The next few lines write an HTTP client request to the socket using the write() method of the BufferedWriter class. The data isn’t actually sent until the flush() method is called. It’s very important to note that the specific syntax of the text sent to the HTTP server is very exacting. While HTTP1.1 is a well-defined protocol, vendors differ in how tolerant they are of deviation from the protocol. We could omit the second line,. the “Host: ” + args[0] + “:80\n\n” line, and this program would still work for most servers we would try. But it wouldn’t work for all of them. And it’s critical that the line ends with two new lines (\n) as opposed to just one.

clientRequest.write(“GET /” + args[1] + “ HTTP/1.1\n”);
clientRequest.write(“Host: “ + args[0] + “:80\n\n”);
clientRequest.flush();

After sending the HTTP GET request to the server through our socket, we use the readLine() method of the BufferedReader class to read back the response from the server through the socket. When there are no more lines, we close the Buffered Reader, the BufferedWriter, and the socket. Since many of these methods throw exceptions, we have a catch() block at the end.

while(serverResponse.readLine() != null) {
System.out.println(serverResponse.readLine());
serverResponse.close();
clientRequest.close();
webSocket.close();
} catch(Exception e){e.printStackTrace();}
}
}

To execute the program, try the following:
c:\> javac HttpSocketClient.java
c:\> java HttpSocketClient www.rhubarbinfo.com index.html
Date: Mon, 15 Jan 2001 13:45:20 GMT
Filter-Revision: 1.90
Content-length: 14580

“http://www.w3.org/TR/REC-html40/loose.dtd”>
<link rel=”STYLESHEET” TYPE=”text/css” HREF=”styles.css”>

[lots of html spews forth, omitted for brevity]
</td></tr><!—msnavigation—></table></body>
null

The program we just described  represents  about the simplest client we could construct. In creating a socket connection to port 80 on a remote machine, it asks to be connected to the service provided at port 80. That service is an  HTTP web server. Next we will construct the corresponding server.

Random Posts

Comments are closed.