// // Chat.java // import java.io.*; import java.awt.*; import java.applet.*; import java.net.*; /** * The TextArea thread that listens to the socket. */ class ServerChat extends TextArea implements Runnable { Chat chat; // the applet public Thread thread; // the thread that this class runs in public int curpos = 0; // current position in the TextArea final static int MAXLENGTH = 5000; // largest message we can handle final static int TEXTAREA_WIDTH = 50; // no. columns in the TextArea final static int TEXTAREA_HEIGHT = 4; // no. rows in the TextArea /** * The constructor. */ public ServerChat(Chat c) { super(TEXTAREA_WIDTH, TEXTAREA_HEIGHT); chat = c; setEditable(false); thread = new Thread(this); } /** * Called when the component is exposed, or when repaint() is called. */ public void update(Graphics g) { paint(g); } /** * Read data from the socket. Blocks. */ public String readln(DataInputStream dis) throws IOException { byte b[] = new byte[MAXLENGTH]; String s; int nchars = dis.read(b, 0, MAXLENGTH); if (nchars > 0) { s = new String(b, 0, 0, nchars); } else { s = ""; } return s; } /** * The thread's main routine, in effect. Called by Thread.start(). */ public void run() { // Read from socket; when there is data, post event to the applet String inData = null; for (;;) { // Wait on a socket read... try {inData = readln(chat.dis);} catch (IOException ex) { System.out.println("IO Exception reading from server"); System.exit(1); } // Write the data to the text area... if (inData.equals("\b")) //Backspace { curpos--; replaceText("", curpos - 1, curpos + 1); } else { insertText(inData, curpos); curpos += inData.length(); } } } } /** * The TextArea that handles user input. */ class UserChat extends TextArea { public int curpos = 0; // the current position in the TextArea final static int TEXTAREA_WIDTH = 50; // no. columns in the TextArea final static int TEXTAREA_HEIGHT = 4; // no. rows in the TextArea /** * The constructor. */ public UserChat() { super(TEXTAREA_WIDTH, TEXTAREA_HEIGHT); curpos = 1; } /** * Write data to the socket. */ public void write(DataOutputStream dos, String s) throws IOException { // Write buffer to the socket dos.writeBytes(s); } /** * Called when the component is exposed, or when repaint() is called. */ public void update(Graphics g) { paint(g); } } /** * The applet. */ public class Chat extends Applet { final static int DEFAULT_FRAME_WIDTH = 600; final static int DEFAULT_FRAME_HEIGHT = 400; //applet dimensions; browser overrides final static String HOSTNAME = "minitorn.tpu.ee"; // the server name final static int PORTNUMBER = 6001; // must match port in server code final static String newline = new String("\n"); String hostname; // the name of the host we connected to int port; // the port we connected to Socket socket; // the socket DataInputStream dis; // a DataInputStream on the socket DataOutputStream dos; // a DataOutputStream on the socket ServerChat serverChat; // the ServerChat object UserChat userChat; // the UserChat object boolean connected = false; // flag indicating if we are connected /** * The constructor. */ public Chat() { setLayout(new GridLayout(2, 1, 10, 10)); Panel panel1 = new Panel(); Panel panel2 = new Panel(); add(panel1); add(panel2); panel1.setLayout(new GridLayout(2, 1, 10, 10)); panel2.setLayout(new GridLayout(2, 1, 10, 10)); // Create input window userChat = new UserChat(); // Create output window serverChat = new ServerChat(this); panel1.add(new Label("Type into Input Window below:")); panel1.add(userChat); panel2.add(new Label("List of messages received and sent:")); panel2.add(serverChat); resize(DEFAULT_FRAME_WIDTH-20, DEFAULT_FRAME_HEIGHT-50); } /** * Establish connection with server and start the monitor thread. */ public void init() { try {makeConnection(HOSTNAME, PORTNUMBER);} catch (Exception ex) { System.out.println("Unable to make connection to host"); connected = false; } connected = true; resize(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT); } /** * Start */ public void start() { if (! connected) return; serverChat.thread.start(); // calls run() } /** * Called when browser leaves this page. */ public void stop() { serverChat.thread.stop(); try {socket.close();} catch (IOException ex) {System.out.println(ex);} connected = false; } /** * Establish a connection with the chat server program. */ void makeConnection(String h, int p) throws java.net.UnknownHostException, IOException { hostname = h; port = p; socket = new Socket(hostname, port); // Issue confirmation to user InetAddress rina = socket.getInetAddress(); System.out.println("Connected to " + rina.toString()); InetAddress lina = rina.getLocalHost(); System.out.println("Local host designation: " + lina.toString()); // Determine the socket's input and output stream handles dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); } /** * Handle all applet events, incl. component events. */ public boolean handleEvent(Event evt) { switch(evt.id) { case Event.KEY_RELEASE: // Handle special case of bug related to the period character if ((char)(evt.key) != '.') return super.handleEvent(evt); case Event.KEY_PRESS: // Append the new char to the TextArea String s = new String(); if ((char)(evt.key) != '\b') t.append((char)(evt.key)); s += (char)(evt.key); if ((t.length() > 70) || (t.length() > 60 && (char)evt.key == ' ')) { t.append("\n"); sendToServer(); userChat.insertText(newline, userChat.curpos); } if ((char)(evt.key) == '\b') //Backspace { userChat.curpos--; userChat.replaceText("", userChat.curpos - 1, userChat.curpos + 1); t.setLength( t.length() - 1); } else if ((char)(evt.key) != '.') // (skip special case) // For all characters except period: { userChat.insertText(s, userChat.curpos); userChat.curpos++; } else userChat.curpos++; // Send the input to the server if ((char)(evt.key) == '\n') sendToServer(); return true; } return super.handleEvent(evt); } private void sendToServer() { String tmp = new String(t); try {userChat.write(dos, tmp);} catch (IOException ex) { System.out.println("IO Exception writint to server"); System.exit(1); } t.setLength(0); } /** * We only need this if we run standalone (not in a browser). */ public static void main(String args[]) { ChatFrame f = new ChatFrame("Chat"); f.chat = new Chat(); f.add("Center", f.chat); f.resize(DEFAULT_FRAME_WIDTH, DEFAULT_FRAME_HEIGHT); f.show(); f.chat.init(); f.chat.start(); } StringBuffer t = new StringBuffer(90); } /** * A closeable frame. Used only by Chat.main(). */ class ChatFrame extends Frame { Chat chat; public ChatFrame(String s) { super(s); } public boolean handleEvent(Event evt) { if (evt.id == Event.WINDOW_DESTROY) { System.exit(0); } return super.handleEvent(evt); } }