Programming Clients Using Sockets
A socket is an abstract input-output device. A socket may correspond to a display, a keyboard, a printer or a data communications line. A socket is used by a program to input or output a stream of data.
A client socket can:
A client socket is normally used as follows:
In Java, the class Socket provides a way of using TCP sockets. (There are other types of socket, including datagram sockets.) The constructor method:
When a socket is created, either the host name is supplied, or an InetAddress object.
Example - A Port Scanner Program
The following program attempts to connect to ports 1 to 256 of a specified host. It thus checks to see which of these ports are "open for business", as it were.
It works by first inputting a host name, then trying to create an InetAddress object. If this fails, the host is unknown and an error message is displayed. The program then tries to open ports 1 to 256 on the host. If a socket is created, there is assumed to be an open port and a message is displayed. If a socket cannot be opened on a port, an exception is raised and the port is simply ignored. It might be helpful to look at
Program Psuedocode
Input host name Check that host exists for port = 1 to 256 do Try to open socket to port if socket opens Display port number Close socket endfor
// PortScanner.java // Scans ports from numbers 1 through 256 and // reports those which are active. import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; public class PortScanner extends Frame implements ActionListener { private TextField hostInput; private TextArea report; private Button button, exit; public static void main(String [] args) { PortScanner lfp = new PortScanner(); lfp.makeGUI(); lfp.setSize(525, 280); lfp.setVisible(true); } public void makeGUI() { setLayout(new FlowLayout()); button = new Button("Enter host name below and click here to " + "display server ports found on that host:"); add(button); hostInput = new TextField("cs.stmarys.ca", 40); add(hostInput); report = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY); add(report); button.addActionListener(this); exit = new Button("Exit"); add(exit); exit.addActionListener(this); } public void actionPerformed(ActionEvent event) { if (event.getSource() == exit) System.exit(0); report.setText(""); String host = hostInput.getText(); try { InetAddress theAddress = InetAddress.getByName(host); for (int i=0; i<256; i++) { try { Socket socket = new Socket(host, i); report.append("There is a server on port " + i + "\n"); socket.close(); } catch (IOException e) { // No server on that port ... // report.append("Exception: Problem on port " + // i + ": " + e.toString()); } } } catch (UnknownHostException e) { report.setText("Unknown host"); } } }
Details about sockets
When a socket is created and a connection established, the server host name and port are specified. But there is also implicitly a client host port number involved, and this is part of the information encapsulated in a socket. This is chosen by the system at run time from available unused ports. The local port number is embedded in the IP packet along with the local host's IP address, so that the server can send the reply back to the right place. This port number can be accessed using getLocalPort(), one of the Socket class object methods (see the reference summary).
A socket is closed when:
Once a socket has been used to connect to a host, the program should close it. This is just good housekeeping.
The methods getInputStream() and getOutputStream() of the class Socket create objects of the classes InputStream and OutputStream, respectively. These can then be used to do stream input and output. It is usually best to create stream objects, which provide better functionality.
Now the world is your oyster - you can write programs to open connections to any host on any port and engage in conversation according to one of the established protocols (or your own special protocol if you can write a server).
Example - The Daytime Protocol (RFC867)
As an example of writing a client, the protocol
daytime
enables a client to obtain the date and time from
port 13 of a host, providing of course that the
host is in fact providing that servie. The client
merely opens the connection, and sends nothing.
In response the server sends a line of text, giving
the current date and time on the server. Once again,
take a look at the
Program Pseudocode
Open a socket to port 13 on the desired computer Open an input stream Read the date and time from the stream Display that date and time Close the socket
// GetRemoteTime.java // Retrieves the time from a "remote" server. import java.awt.*; import java.awt.*; import java.awt.event.*; import java.net.*; import java.io.*; public class GetRemoteTime extends Frame implements ActionListener { private TextField hostInput; private TextArea display; private Button button; private Button exit; public static void main(String [] args) { GetRemoteTime gr = new GetRemoteTime(); gr.makeGUI(); gr.setSize(550, 300); gr.setVisible(true); } public void makeGUI() { setLayout(new FlowLayout()); hostInput = new TextField(50); add(hostInput); button = new Button("Get time from this host"); add(button); display = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY); add(display); button.addActionListener(this); exit = new Button("Exit"); add(exit); exit.addActionListener(this); } public void actionPerformed(ActionEvent event) { if (event.getSource() == exit) System.exit(0); String theTime; String host = hostInput.getText(); try { Socket socket = new Socket(host, 13); BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); theTime = input.readLine(); display.append("The time at " + host + " is " + theTime + ". "); socket.close(); } catch (UnknownHostException e) { display.setText("No such host. "); } catch (IOException io) { display.setText(io.toString()); } } }
When you run this program, try entering localhost as the host name, to connect back to your own machine.
Errors and Exceptions
Several things can go wrong when a socket is created and a connection sought or used:
A ConnectException means thatthe connection is refused by the remote host. This may be because the host is busy, or because there is no server on that port.
A NoRouteToHostException means thatthe connection has timed out.
Normally, when a program reads from a socket, the call on the read thread blocks (waits) until the data has been obtained. But if the remote host crashes, the program is left hanging. An alternative is to call setSoTimeout to set the maximum waiting time. When this time expires, an InterruptedException is thrown.
Inputting and Outputting with Sockets
A socket connection can be used in both directions at once.
For input, it is most convenient to create a BufferedReader as follows:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Thereafter, method readLine can be used to input a complete line as a string (minus the terminating character(s)):
String string = in.readLine();
The end of the stream is signalled by a string equal to the null object. Thus a common pattern for input is:
String string; while((string = in.readLine()) != null) { processLine(); }
For output to a stream, it is most convenient to create a PrintWriter object like
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
and thereafter use method println to output a line (the line terminator is automatically added):
out.println("string");
Closing a socket closes all of the associated streams.
So, Java provides a Socket class that allows us to connect machines over a network or the Internet:
Class name: |
Socket |
Import: |
|
Summary of class Socket Info
Method |
Description |
Example |
Constructors: |
|
|
public Socket(String host, int port) |
Creates a new Socket object corresponding to destination host and port |
Socket socket = new Socket("www.shu.ac.uk", 80); |
public Socket(InetAddress host, int port) |
Creates a new Socket object corresponding to the InetAddress object and port |
Socket socket = new Socket(inetAddress, 80); |
Object Methods: |
|
|
public InetAddress getInetAddress() |
Returns the InetAddress object corresponding to the host that is, or will be, connected to. |
InetAddress iNE = socket.getInetAddress(); |
public int getPort() |
Returns the port number of the host to which the socket is, or will be, connected. |
int port = socket.getPort(); |
public int getLocalPort() |
Returns the local port number. |
int port = socket.getLocalPort(); |
public InputStream getInputStream() |
Returns an input stream that can be used by the program for input. |
InputStream is = socket.getInputStream(); |
public OutputStream getOutputStream() |
Returns an output stream that can be used by the program for output. |
OutputStream os = socket.getOutputStream(); |
public synchronized void close() |
Disconnects a socket. This also closes the streams associated with the socket. |
socket.close(); |
public String toString() |
Returns a string representation of a socket with remote host name, remote IP address, remote port, local port. |
String details = socket.toString() |
public synchronized void setSoTimeout(int ms) |
Sets the time-out to the parameter value (in milliseconds). |
socket. setSoTimeout(18000); |
Summary of class BufferedReader Info
Method |
Description |
Example |
public String readLine() |
Inputs a string that is followed by a line terminator. The string does not include the terminator. |
in.readLine(); |
Summary of class PrintWriter Info
Method |
Description |
Example |
public void println(String) |
Outputs a string, followed by a line terminator. |
out.println("output line"); |
Questions: The goal of these questions is to help you clarify the understanding of ports and sockets:
Exercises: The goal of these exercises is to help clarify the meaning of a "connection":
Exercises: The goal of these exercises is to help you to understand sockets:
Run the program GetRemoteTime.java given above.
echo
protocol to communicate with a server, one line
at a time. Use separate text areas for the text
sent to the server and the text sent from the
server. Use a text field to specify the host name.
Use a button to close the connection.
Write a program that uses the finger
protocol to get information about users of a host.
Write a program that acts as a general-purpose
telnet
client. The program should provide: