You are on page 1of 18

1

Socket Programming in Java


Java provides several useful classes for simplifying internet and socket programming. These include InetAddress for obtaining IP addresses from domain names, URL and URLConnection classes for communicating with web servers, and Socket and ServerSocket classes for creating general client server programs. We will examine the above classes through several examples:

Example 1: Use of InetAddress class


// Demonstrate InetAddress. import java.net.*; class InetAddressTest { public static void main(String args[]) throws UnknownHostException { InetAddress Address = InetAddress.getLocalHost(); System.out.println(Address); Address = InetAddress.getByName("fox.Bridgeport.edu"); System.out.println(Address); InetAddress SW[] = InetAddress.getAllByName("www.nba.com"); for (int i=0; i<SW.length; i++) System.out.println(SW[i]); } }

If you compile and run the above program while you are connected to the internet, you will see an output like:

Example 2: URL and URLConnection classes


// UCDemo.java Demonstrate URLConnection. import java.net.*; import java.io.*; import java.util.Date; class UCDemo { public static void main(String args[]) throws Exception { int c; URL hp = new URL("http://fox.bridgeport.edu");

2
URLConnection hpCon = hp.openConnection(); System.out.println("Date: " + new Date(hpCon.getDate())); System.out.println("Content-Type: " + hpCon.getContentType()); System.out.println("Expires: " + hpCon.getExpiration()); System.out.println("Last-Modified: " + new Date(hpCon.getLastModified())); int len = hpCon.getContentLength(); System.out.println("Content-Length: " + len); if (len > 0) { System.out.println("=== Content ==="); InputStream input = hpCon.getInputStream(); int i = len; while (((c = input.read()) != -1) && (--i > 0)) { System.out.print((char) c); } input.close(); } else { System.out.println("No Content Available"); } } }

Example 3: Socket class is used to make TCP clients. Its constructor identifies the TCP
server (domain name or IP address) and the port number on which to connect to. The following program connects to the port 43 (Who is port on the internic server to find out if a given domain is registered or not and if so information about it).
// ---Whois.java--- Demonstrate Sockets. import java.net.*; import java.io.*; class Whois { public static void main(String args[]) throws Exception { int c; Socket s = new Socket("internic.net", 43); InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); String str = (args.length == 0 ? "bridgeport.edu" : args[0]) + "\n"; byte buf[] = str.getBytes(); out.write(buf); while ((c = in.read()) != -1) { System.out.print((char) c); } s.close(); } }

Example 4: If you modify the above program to connect to a web server (most web
servers are listening on port 80), then by sending the following string: GET /default.htm HTTP/1.0 \n\n to the socket that is connected to the web server, you will get the page back on the socket.
// ---Whois.java--- Demonstrate Sockets. import java.net.*; import java.io.*;

class Whois { public static void main(String args[]) throws Exception { int c; // Socket s = new Socket("internic.net", 43);

Socket s = new Socket("fox.bridgeport.edu", 80);


InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); // String str = (args.length == 0 ? "bridgeport.edu" : args[0]) + "\n";

String str = "GET /default.asp HTTP/1.0\n\n";


byte buf[] = str.getBytes(); out.write(buf); while ((c = in.read()) != -1) { System.out.print((char) c); } s.close(); } }

Example 5: Another example illustrating use of Client sockets to contact a Daytime


server on port 13.
import java.net.*; //---DaytimeClient.java import java.io.*;

5
// Contact the daytime server running on hostname. class DaytimeClient { // Contact the server at the appropriate port and set // the socket attribute for the run() method to use. public DaytimeClient(String hostname) throws Exception { // The well-known port of the TCP daytime service. final int DaytimePort = 13; try{ socket = new Socket(hostname,DaytimePort); } catch(UnknownHostException e){ throw new Exception("Unknown host: "+e.getMessage()); } catch(IOException e){ throw new Exception("IOException on socket creation: "+e.getMessage()); } } // Obtain the time of day from the daytime server. public void run() { Socket daytime = getSocket(); try{ // Get the stream used by the server to send data. InputStream inStream = daytime.getInputStream(); // Wrap the stream in a BufferedReader. BufferedReader reader = new BufferedReader( new InputStreamReader(inStream)); // The server will only send a single line. String response = reader.readLine(); System.out.println(response); // Close the connection now it is finished with. daytime.close(); } catch(IOException e){ System.err.println(e.getMessage()); } } protected Socket getSocket(){ return socket; } private final Socket socket; }

// ----DaytimeMain.java // Illustrate connection to a daytime server running on // the host named in the command line argument. public class DaytimeMain { public static void main(String[] args) { if(args.length == 1){ try{

6
DaytimeClient client = new DaytimeClient(args[0]); client.run(); } catch(Exception e){ System.err.println("Exception: "+e.getMessage()); } } else{ System.err.println("You must supply the name of a host to contact."); } } }

Example 6: A socket is a two way communication mechanism. When you contact a TCP
server, you need to flush the data that is to be written to the output stream (especially if it is a buffered stream). The following example connects to a TCP echo server on port 7. The echo server simply echoes back the data that was sent to it on the socket.
//---TCPEchoClient.java---import java.net.*; import java.io.*; // Contact the echo server running on hostname. class TCPEchoClient { // Contact the server at the appropriate port and set // the socket attribute for the run() method to use. public TCPEchoClient(String hostname) throws Exception { try{ // The well-known port of the TCP echo service. final int EchoPort = 7; socket = new Socket(hostname,EchoPort); } catch(UnknownHostException e){ throw new Exception("Unknown host: "+e.getMessage()); } catch(IOException e){ throw new Exception("IOException on socket creation: "+e.getMessage()); } } // Send the sample strings to the echo server and read // back the responses. public void run(String[] sampleStrings) { Socket echo = getSocket();

try{ // Wrap the input stream in a BufferedReader. BufferedReader reader = new BufferedReader( new InputStreamReader(echo.getInputStream())); // Wrap the output stream in a BufferedWriter. BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(echo.getOutputStream())); // Send each string and read the response. for(int i = 0; i < sampleStrings.length; i++){ String sample = sampleStrings[i]; System.out.println("Sending: "+sample); writer.write(sample); writer.newLine(); // Make sure the data is flushed to the stream. writer.flush(); // Read the response. String response = reader.readLine(); System.out.println("The response is: "+response); } // Close the connection now it is finished with. echo.close(); } catch(IOException e){ System.err.println(e.getMessage()); } } protected Socket getSocket(){ return socket; } private final Socket socket; }

//----TCPEchoMain.java----------------------------------------------------------------// Illustrate connection to a TCP echo server running on // the host named in the command line argument. public class TCPEchoMain { public static void main(String[] args) { if(args.length == 1){ try{ TCPEchoClient client = new TCPEchoClient(args[0]); // Strings to send and have echoed. String[] sampleStrings = { "Hello, echo server.", "Goodbye.", }; client.run(sampleStrings); } catch(Exception e){

8
System.err.println("Exception: "+e.getMessage()); } } else{ System.err.println("You must supply the name of a host to contact."); } } }

Since most of the time, the client-side socket code is similar to the above example, it can be encapsulated in a class to provide a more object-oriented look to the client code. For example, the buffered reader and writer creation on socket streams can be put inside a class called TCPEndpoint.java as shown below. In addition methods can be provided (sendLine) that automatically flush the buffer so that the user is not concerned about taking care of these. //----TCPEndpoint.java----------------------// A class that maintains the attributes of a TCP endpoint. // This class looks after the socket attribute and // buffered reader and writer associated with the // two streams of a TCP communication. // Typical clients and servers extend this class to provide // the functionality applicable to their application. import java.net.*; import java.io.*; class TCPEndpoint { // Contact the server at the appropriate port and set // the socket attribute for the run() method to use. public TCPEndpoint(String hostname,int port) throws Exception { try{ Socket socket = new Socket(hostname,port); // Setup the socket attribute and associated streams. setSocket(socket); } catch(UnknownHostException e){ throw new Exception("Unknown host: "+e.getMessage()); } catch(IOException e){

9
throw new Exception("IOException on socket creation: "+ e.getMessage()); } } // A connection has already been established. // Setup the socket attribute and associated streams. public TCPEndpoint(Socket socket) throws Exception { setSocket(socket); } // Get the next line from the server. protected String getLine() throws IOException { return getReader().readLine(); } // Flush the given line to the server. protected void sendLine(String line) throws IOException { bufferLine(line); getWriter().flush(); } // Send the given line to the server without flushing. protected void bufferLine(String line) throws IOException { BufferedWriter writer = getWriter(); writer.write(line); writer.newLine(); } // Close the socket. protected void close() { Socket sock = getSocket(); try{ sock.close(); } catch(IOException e){ // Not much we can do about this. } } protected Socket getSocket(){ return socket; } // Setup the socket attribute and create an // associated Reader and Writer for the associated // streams. protected void setSocket(Socket s) throws Exception { if(s != null){ socket = s; // Wrap the input stream in a BufferedReader. setReader(new BufferedReader( new InputStreamReader(socket.getInputStream()))); // Wrap the output stream in a BufferedWriter. setWriter(new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())));

10
} else{ throw new Exception("Null socket passed to setSocket."); } } protected BufferedReader getReader(){ return reader; } protected void setReader(BufferedReader r){ reader = r; } protected BufferedWriter getWriter(){ return writer; } protected void setWriter(BufferedWriter w){ writer = w; } private Socket socket; // Buffered reader and writer for the socket's streams. private BufferedReader reader; private BufferedWriter writer; }

Here is an example that uses the above TCPEndpoint class to make a client to a web server. Example 7:
//-----HTTPClient.java----------import java.net.*; import java.io.*; // Use the HTTP server running on hostname. class HTTPClient extends TCPEndpoint { // Contact the server at the appropriate port and set // the socket attribute for the run() method to use. public HTTPClient(String hostname) throws Exception { // The well-known port of the HTTP service. super(hostname,HTTPPort); } // Retrieve the given filename from the HTTP server. public String retrieve(String filename) throws IOException { try{ // Send the retrieval command. sendLine("GET "+filename + " HTTP/1.0\n");

11
// The line to be returned will be built up in this. StringBuffer line = new StringBuffer(); // Read and print the responses. String response = getLine(); while(response != null){ line.append(response+"\n"); response = getLine(); } return line.toString(); } finally{ // Close the connection now it is finished with. close(); } } // The well-known port of the HTTP server. private static final int HTTPPort = 80; } //------HTTPMain.java------------------------------------// Illustrate use of the TCPEndpoint class by building // a client of an HTTP server with it. public class HTTPMain { public static void main(String[] args) { if(args.length == 1){ try{ HTTPClient client = new HTTPClient(args[0]); // Print what the client retrieves. System.out.println(client.retrieve("/default.asp")); } catch(Exception e){ System.err.println("Exception: "+e.getMessage()); } } else{ System.err.println("You must supply the name of a host to contact."); } } }

If you run the above program as java HTTPMain fox.Bridgeport.edu you will receive the same output as in example 4.

Creating TCP servers using the java ServerSocket class. The java ServerSocket class constructor creates the server socket, binds it to a port and goes into listening mode. The class provides an accept method which is a blocking call and waits for the incoming client.

12

Example 8: Line length server.


//-----LineLengthServer.java--------------import java.net.*; import java.io.*; // A simple server that accepts a client connection // and sends back the length of the strings it // receives from the client. class LineLengthServer { public LineLengthServer(int port) throws Exception { try{ // Listen on the given port. serverSocket = new ServerSocket(port); } catch(BindException e){ throw new Exception("Failed to create a server socket: "+ e.getMessage()); } } // Read strings and return their length (as a String) // to the client. public void run() throws Exception { ServerSocket serverSocket = getServerSocket(); Socket clientSocket = null; try{ System.out.println("Listening for a client on port: "+ serverSocket.getLocalPort()); // Wait for a client to make contact. clientSocket = serverSocket.accept(); // Contact ... System.out.println("A client has arrived."); // Wrap the input stream in a BufferedReader. BufferedReader reader = new BufferedReader( new InputStreamReader(clientSocket.getInputStream())); // Wrap the output stream in a BufferedWriter. BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream())); // Read lines until the client terminates. String request = reader.readLine(); while(request != null){ // Write the length of the line as a String. writer.write(String.valueOf(request.length())); writer.newLine(); writer.flush(); request = reader.readLine(); } } catch(IOException e){ throw new Exception("IOException talking to the client: "+ e.getMessage()); }

13
finally{ if(clientSocket != null){ System.out.println("The client has gone."); // Close the socket to the client. clientSocket.close(); } } serverSocket.close(); } protected ServerSocket getServerSocket(){ return serverSocket; } // The socket on which the listening is done. private final ServerSocket serverSocket; }

//-----LineLengthServerMain.java--------------------------------------// An example of a simple server that reads lines from // clients and sends back the length of each line // it receives. public class LineLengthServerMain { public static void main(String[] args){ try{ // An arbitrary port number to listen on. This should be // larger than 1024 for user-written servers. final int port = 2001; LineLengthServer server = new LineLengthServer(port); server.run(); } catch(Exception e){ System.err.println("Exception: "+e.getMessage()); } } }

We can modify the client from example 4 to connect to the LineLength server on port 2001
//---TCPLineClient.java --------------------------------------import java.net.*; import java.io.*; // Contact the line length server running on hostname. class TCPLineClient { // Contact the server at the appropriate port and set // the socket attribute for the run() method to use. public TCPLineClient(String hostname) throws Exception { try{ // The well-known port of the TCP echo service.

14
final int LinePort = 2001; socket = new Socket(hostname,LinePort); } catch(UnknownHostException e){ throw new Exception("Unknown host: "+e.getMessage()); } catch(IOException e){ throw new Exception("IOException on socket creation: "+e.getMessage()); } } // Send the sample strings to the echo server and read // back the responses. public void run(String[] sampleStrings) { Socket lineclnt = getSocket(); try{ // Wrap the input stream in a BufferedReader. BufferedReader reader = new BufferedReader( new InputStreamReader(lineclnt.getInputStream())); // Wrap the output stream in a BufferedWriter. BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(lineclnt.getOutputStream())); // Send each string and read the response. for(int i = 0; i < sampleStrings.length; i++){ String sample = sampleStrings[i]; System.out.println("Sending: "+sample); writer.write(sample); writer.newLine(); // Make sure the data is flushed to the stream. writer.flush(); // Read the response. String response = reader.readLine(); System.out.println("The response is: "+response); } // Close the connection now it is finished with. lineclnt.close(); } catch(IOException e){ System.err.println(e.getMessage()); } } protected Socket getSocket(){ return socket; } private final Socket socket; }

//----TCPLineMain.java----------------------------------

15
// Illustrate connection to a TCP echo server running on // the host named in the command line argument. public class TCPLineMain { public static void main(String[] args) { if(args.length == 1){ try{ TCPLineClient client = new TCPLineClient(args[0]); // Strings to send and have echoed. String[] sampleStrings = { "Hello, echo server.", "Goodbye.", }; client.run(sampleStrings); } catch(Exception e){ System.err.println("Exception: "+e.getMessage()); } } else{ System.err.println("You must supply the name of a host to contact."); } } }

You need to compile and run the LineLengthServer in a separate DOS window. Then through another DOS Window if you run the TCPLineMain program (client program), you will see the output as:

Handling Concurrent clients: The previous example of the TCP server only allowed one client to be connected to the server at a time. We can make a

16

TCP server more responsive by having it create a separate thread for each client as the server does an accept of an incoming connection. Example 9:
//---------RandomServiceListener.java-------------import java.net.*; import java.io.*; // A server that accepts multiple client connections. // The service, implemented by the RandomService class, // sends random integers when requested. class RandomServiceListener { public RandomServiceListener(int port) throws Exception { try{ // Listen on port. serverSocket = new ServerSocket(port); } catch(BindException e){ throw new Exception("Failed to create a server socket: "+ e.getMessage()); } } // Listen for clients. When each arrives, hand the socket // over to a RandomService slave. public void listen() throws Exception { ServerSocket serverSocket = getServerSocket(); // Wait up to 30 minutes for new clients. final int timeToWait = 1*60*1000; boolean keepWaiting = true; while(keepWaiting){ try{ // Wait for a client to make contact. serverSocket.setSoTimeout(timeToWait); Socket clientSocket = serverSocket.accept(); // Let a separate Thread handle it. new Thread(new RandomService(clientSocket)).start(); } catch(InterruptedIOException e){ // We timed out waiting for a client. keepWaiting = false; } catch(IOException e){ throw new Exception("IOException: "+ e.getMessage()); } } // No more clients, so close the socket. serverSocket.close(); } protected ServerSocket getServerSocket(){ return serverSocket;

17
} // The socket on which the listening is done. private final ServerSocket serverSocket; }

//-------RandomService.java---------import java.net.*; import java.io.*; import java.util.Random; // Provide random integers to the client on request. // The text of any request is ignored but used // as a prompt for when to send each number. class RandomService extends TCPEndpoint implements Runnable { public RandomService(Socket s) throws Exception { super(s); } // Supply random integers on request to the client. public void run(){ // The random number generator for this client. Random random = new Random(); try{ String request = getLine(); while(request != null){ // We are not interested in the text of the request. sendLine(""+random.nextInt()); request = getLine(); } } catch(IOException e){ System.err.println("IOException: "+e.getMessage()); } finally{ close(); System.out.println("Thread terminating."); } } }

//--------RandomServiceMain.java---------// Test rig for a simple server that accepts client connections // and sends back random integers when requested. public class RandomServerMain { public static void main(String[] args){ try{

18
// An arbitrary port number to listen on. This should be // larger than 1024 for user-written servers. final int port = 24102; RandomServiceListener server = new RandomServiceListener(port); server.listen(); } catch(Exception e){ System.err.println("Exception: "+e.getMessage()); } } }

You might also like