Recent Changes - Search:

Network Programming

This website demonstrates using wikis as teaching and learning tool.

The course instructor is happy to share the teaching materials here with those who find it readable.

Tutorial - Java Network Programming - Internet Chat Example

Overview - This tutorial is about building an internet chat application. You will study how to program this common and well-known Internet application.


Activity 1

Let's begin by looking at the product we are going to build before we study how to program this common and well-known Internet application. First of all, use the source code provided to compile into the required byte-codes and execute these byte-codes to see the capability and features of the chat application.
Compile, run, and test the chat client and chat server according to the following steps.
1. Compile the source code ChatClient.java, and ChatServer.java to generate the class files.
2. Then run the chat server program by executing the ChatServer.class:
java ChatServer
3. After that, test the server by launching the client program several times to connect to the server:
java ChatClient
4. Test the client/server chat application by typing text into the input region of a different client's windows to see whether they work as expected.

Illustration of the program


Activity 2

Question 1: In the main method of ChatClient, there are default values for the server and port number. What are they?
Question 2: How can the server and port number be specified when executing the program?
The chat client program we just studied sends only the input message to the server and does not tell the server the identity of the user. This makes the messages displayed in the output region indistinguishable. This situation can be easily remedied by slightly modifying the client program.
Task: Modify the chat client program in a way that when the client sends a message to the server, the username of the client is attached to the message being sent. The user can specify the username via the command line argument. Set the default value to be "guest" when the user does not specify it.
Submit your works in Activity 2 to Steven.

Activity 3

  • Test the Chat Client and Chat Server programs with a remote PC in the network.
  • Test the Chat Client and Chat Server programs across the Internet in your spare time. How?

Java Source Code

Chat Server

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ChatServer {

    private static Logger logger = Logger.getLogger("ChatServer");
    private static Observable observable = new Observable() {
        @Override
        public void notifyObservers(Object arg) {
            super.setChanged();
            super.notifyObservers(arg);
        }
    };

    /** Handler for an individual client */
    static class ClientHandler implements Runnable, Observer {
        private Socket socket;
        private OutputStream outputStream;

        ClientHandler(Socket socket) {
            this.socket = socket;
        }

        /** Perform echoing to the client socket */
        public void run() {
            logger.info("Accepted client " + socket.getInetAddress() + ":"
                    + socket.getPort());
            observable.addObserver(this);
            try {
                outputStream = socket.getOutputStream();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(socket.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    observable.notifyObservers(line);
                }
                socket.close();
            } catch (IOException ex) {
                logger.log(Level.SEVERE, null, ex);
            }
            logger.info("Disconnected client " + socket.getInetAddress() + ":"
                    + socket.getPort());
            observable.deleteObserver(this);
        }

        private static final String CRLF = "\r\n"; // newline

        public void update(Observable o, Object arg) {
            try {
                outputStream.write((arg + CRLF).getBytes());
                outputStream.flush();
            } catch (IOException ex) {
                logger.log(Level.SEVERE, null, ex);
            }
        }
    }

    public static void main(String[] args) {

        int port = args.length > 0 ? Integer.parseInt(args[0]) : 1055;
        try {
            ServerSocket server = new ServerSocket(port);
            logger.info("Server started, listening at port " + port + " ...");
            ExecutorService executor = Executors.newCachedThreadPool();
            while (true) {
                Socket socket = server.accept();
                ClientHandler handler = new ClientHandler(socket);
                executor.execute(handler);
            }
        } catch (IOException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }
}

Chat Client

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
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 ChatClient {

    /** Chat client access */
    static class ChatAccess extends Observable {
        private Socket socket;
        private OutputStream outputStream;

        @Override
        public void notifyObservers(Object arg) {
            super.setChanged();
            super.notifyObservers(arg);
        }

        /** Create socket, and receiving thread */
        public ChatAccess(String server, int port) throws IOException {
            socket = new Socket(server, port);
            outputStream = socket.getOutputStream();

            Thread receivingThread = new Thread() {
                @Override
                public void run() {
                    try {
                        BufferedReader reader = new BufferedReader(
                                new InputStreamReader(socket.getInputStream()));
                        String line;
                        while ((line = reader.readLine()) != null)
                            notifyObservers(line);
                    } catch (IOException ex) {
                        notifyObservers(ex);
                    }
                }
            };
            receivingThread.start();
        }

        private static final String CRLF = "\r\n"; // newline

        /** Send a line of text */
        public void send(String text) {
            try {
                outputStream.write((text + CRLF).getBytes());
                outputStream.flush();
            } catch (IOException ex) {
                notifyObservers(ex);
            }
        }

        /** Close the socket */
        public void close() {
            try {
                socket.close();
            } catch (IOException ex) {
                notifyObservers(ex);
            }
        }
    }

    /** Chat client UI */
    static class ChatFrame extends JFrame implements Observer {

        private JTextArea textArea;
        private JTextField inputTextField;
        private JButton sendButton;
        private ChatAccess chatAccess;

        public ChatFrame(ChatAccess chatAccess) {
            this.chatAccess = chatAccess;
            chatAccess.addObserver(this);
            buildGUI();
        }

        /** Builds the user interface */
        private void buildGUI() {
            textArea = new JTextArea(20, 50);
            textArea.setEditable(false);
            textArea.setLineWrap(true);
            add(new JScrollPane(textArea), BorderLayout.CENTER);

            Box box = Box.createHorizontalBox();
            add(box, BorderLayout.SOUTH);
            inputTextField = new JTextField();
            sendButton = new JButton("Send");
            box.add(inputTextField);
            box.add(sendButton);

            // Action for the inputTextField and the goButton
            ActionListener sendListener = new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String str = inputTextField.getText();
                    if (str != null && str.trim().length() > 0)
                        chatAccess.send(str);
                    inputTextField.selectAll();
                    inputTextField.requestFocus();
                }
            };
            inputTextField.addActionListener(sendListener);
            sendButton.addActionListener(sendListener);

            this.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    chatAccess.close();
                }
            });
        }

        /** 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() {
                    textArea.append(finalArg.toString());
                    textArea.append("\n");
                }
            });
        }
    }

    public static void main(String[] args) {
        String server = args.length >= 1 ? args[0] : "localhost";
        int port = args.length >= 2 ? Integer.parseInt(args[1]) : 1055;
        ChatAccess access = null;
        try {
            access = new ChatAccess(server, port);
        } catch (IOException ex) {
            System.out.println("Cannot connect to " + server + ":" + port);
            ex.printStackTrace();
            System.exit(0);
        }
        JFrame frame = new ChatFrame(access);
        frame.setTitle("Chat Client - connected to " + server + ":" + port);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setVisible(true);
    }
}

Edit - History - Print - Recent Changes - Search
Page last modified on October 21, 2010, at 02:05 PM