|
Distributed Computing This website demonstrates using wikis as teaching and learning tool. The course instructor is also happy to share the teaching materials here with those who find it readable. |
Tutorial /
Tutorial - Building a Web Chat ProgramActivity 1: Using telnet to access a web page
C:\> telnet www.ouhk.edu.hk 80
C:\> GET /index.html HTTP/1.0
Notes for your understanding :
HTTP communication can be divided into two separate parts, namely, HTTP requests and HTTP responses.
An HTTP request, which is made by a web client, contains information about a resource on the web server, and the action the client wishes the server to perform on the resource.
A web server fulfils an HTTP request by returning an HTTP response, which varies with the type of request and whether or not the request could be serviced.
Activity 2: Using a Java program to access a web pageNow, let’s look at the source code of a Java program that connects to a web server using the Socket’s API.
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner; public class WebClient { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Enter host name (e.g., www.ouhk.edu.hk): "); String host = scanner.nextLine(); System.out.print("Enter page (e.g., /index.html): "); String page = scanner.nextLine(); final String CRLF = "\r\n"; // newline final int PORT = 80; // default port for HTTP try { Socket socket = new Socket(host, PORT); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); PrintWriter writer = new PrintWriter(os); writer.print("GET " + page + " HTTP/1.0" + CRLF); writer.print(CRLF); writer.flush(); // flush any buffer BufferedReader reader = new BufferedReader( new InputStreamReader(is)); String line; while ((line = reader.readLine()) != null) System.out.println(line); socket.close(); } catch (IOException ex) { ex.printStackTrace(); } } } Notes for your understanding :
The program first asks the user for the host name of the web server and the web page to be retrieved, and stores them in the host and page variables, respectively. Two constants, CRLF and PORT, are then defined for the end-of-line and default port number of HTTP.
The socket accessing code is enclosed in a try-catch block, due to the possible occurrence of IOException on network errors. In the try-catch block, a socket is created with the entered host name and the default port of 80. The output stream and input stream of the socket are obtained by calling the getOutputStream and getInputStream methods on the socket, respectively.
As HTTP is a text-based protocol, we wrap the binary OutputStream and InputStream into character-based streams for writing and reading lines of text. More specifically, a PrintWriter is created to wrap the OutputStream and two strings are written by using its print method. The two strings are a GET request line and an empty line. After that, the flush method is invoked on the PrintWriter to ensure that the output data in the buffer (of the Java implementation and/or the operating system) are actually sent down to the network.
With the HTTP request sent to the server, the program uses the BufferedReader class to obtain the input from the InputStream of the socket. The lines of input are read using the readLine method of BufferedReader in a while loop and printed to the screen, until readLine returns null which denotes the end of the input stream. At the end, we invoke the close method on the socket to free any resources used by it.
Your tasks : Compile and run the above program. Study the program and answer the following questions
Activity 3: A GUI web client exampleimport java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Observable; import java.util.Observer; import javax.swing.Box; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; public class WebClientGUI { /** Web client networking */ static class WebClientAccess extends Observable { /** Requests the url */ public void request(final String url, WebClientFrame clientFrame) { addObserver(clientFrame); Thread socketThread = new Thread() { // for long socket operations @Override public void run() { connect(url); } }; socketThread.start(); } /** Formats url by removing protocol:// and appending / if necessary */ private String parseUrl(String url) { String s = url; int pos = s.indexOf("://"); // if it has protocol:// if (pos >= 0) // found s = s.substring(pos+3); // trim protocol:// pos = s.indexOf('/'); // if it has /page.html part if (pos < 0) // not found s = s + "/"; // add default / as page return s; } private static final int PORT = 80; // default port for HTTP private static final String CRLF = "\r\n"; // newline /** Makes connection using host and page */ private void connect(String url) { String s = parseUrl(url); String host = s.substring(0, s.indexOf('/')); String page = s.substring(s.indexOf('/')); try { Socket socket = new Socket(host, PORT); PrintWriter writer = new PrintWriter(socket.getOutputStream()); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); writer.print("GET " + page + " HTTP/1.0" + CRLF); writer.print(CRLF); writer.flush(); // flush any buffer String line; while ((line = reader.readLine()) != null) { setChanged(); notifyObservers(line); } socket.close(); } catch (IOException ex) { setChanged(); notifyObservers("Exception: " + ex); } setChanged(); notifyObservers(true); } } /** Web client UI */ static class WebClientFrame extends JFrame implements Observer { private JTextField urlTextField; private JButton getButton; private JTextArea textArea; public WebClientFrame() { super("WebClientGUI"); buildGUI(); } /** Builds the user interface */ private void buildGUI() { Box box = Box.createHorizontalBox(); add(box, BorderLayout.NORTH); urlTextField = new JTextField(); getButton = new JButton("Get"); box.add(urlTextField); box.add(getButton); textArea = new JTextArea(30, 80); textArea.setEditable(false); textArea.setLineWrap(true); add(new JScrollPane(textArea), BorderLayout.CENTER); // Action for the urlTextField and the goButton ActionListener goListener = new ActionListener() { public void actionPerformed(ActionEvent e) { String inputURL = urlTextField.getText(); if (inputURL != null && inputURL.trim().length() > 0) { setEnableInputUI(false); textArea.setText(""); WebClientAccess webClient = new WebClientAccess(); webClient.request(inputURL.trim(), WebClientFrame.this); } } }; urlTextField.addActionListener(goListener); getButton.addActionListener(goListener); } /** Enables or disables the input url text field and get button */ private void setEnableInputUI(boolean enable) { urlTextField.setEnabled(enable); getButton.setEnabled(enable); } /** Updates the UI depending on the Object argument */ public void update(Observable o, Object arg) { final Object finalArg = arg; SwingUtilities.invokeLater(new Runnable() { public void run() { if (finalArg instanceof Boolean) // enable or disable UI setEnableInputUI((Boolean) finalArg); else if (finalArg instanceof String) { // append string textArea.append((String) finalArg); textArea.append("\n"); } } }); } } public static void main(String[] args) { JFrame frame = new WebClientFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setResizable(false); frame.setVisible(true); } } Your tasks : Compile, run and study the above program. It teaches you multi-thread programming and the observer design pattern.
|