Friday, July 13, 2012

Java Socket Chat Application v0.1

This is a project for a couple of my CS1332 students. I have been working with them explaining how sockets and networking works specifically related to Java sockets. This is a quick proof of concept application that I threw together just to make sure that I was leading them in the right direction.

Right now it is an infinite loop that checks to see if the user has submitted text to the console or if the socket has received a string. All text is logged to an output file on each machine with the correct prefix to each message (">>" for incoming and "<<" for outgoing).



Code can be found below.

Server.java

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {
        try {
            ServerSocket sSocket = new ServerSocket(3000);
            Socket socket = sSocket.accept();
            System.out.println(\"Client accepted\");
            Chatter c = new Chatter(socket, \"Server.log\");
            c.run();
        } catch (IOException e) {
            // ignore
        }
    }
}

Client.java

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {

    public static void main(String[] args) {
        try {
            ServerSocket sSocket = new ServerSocket(3000);
            Socket socket = sSocket.accept();
            System.out.println(\\\"Client accepted\\\");
            Chatter c = new Chatter(socket, \\\"Server.log\\\");
            c.run();
        } catch (IOException e) {
            // ignore
        }
    }
}

Chatter.java

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Chatter {
    private Socket socket;
    private BufferedInputStream bis;
    private ObjectInputStream ois;
    private ObjectOutputStream oos;
    private BufferedInputStream console_bis;
    private Scanner scanner;
    private BufferedWriter bfw;

    public Chatter(Socket socket, String logName) {
        try {
            this.socket = socket;
            this.bis = new BufferedInputStream(socket.getInputStream());
            this.oos = new ObjectOutputStream(socket.getOutputStream());
            this.console_bis = new BufferedInputStream(System.in);
            this.scanner = new Scanner(console_bis);
            this.bfw = new BufferedWriter(new FileWriter(new File(logName), true));
            this.bfw.append(\"\\n\\n\"
                    + new SimpleDateFormat(\"yyyy/MM/dd HH:mm:ss\")
                            .format(new Date()) + \"\\n===================\\n\");
            this.bfw.flush();
            
            this.ois = new ObjectInputStream(bis);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        String temp = \"\";
        while (temp == null || !temp.equals(\"quit\")) {
            temp = readSocketMessage();
            if (temp != null) {
                if (temp.equals(\"quit\")) {
                    System.out.println(\"[[ Other User Logged Off ]]\");
                    close();
                    System.exit(0);
                }
                logMessage(temp, true);
            }
            temp = readConsoleMessage();
            if (temp != null) {
                sendMessage(temp);
                logMessage(temp, false);
            }
        }
        this.close();
    }
    
    private void close() {
        try {
            socket.close();
        } catch (IOException e) {
            // ignore
        }
        try {
            bfw.close();
        } catch (IOException e) {
            // ignore
        }
    }

    private String readSocketMessage() {
        try {
            if (bis.available() > 0) {
                return (String) ois.readObject();
            }
        } catch (IOException e) {
            System.err
                    .println(\"Fatal Socket Exception: could not read message.\");
            System.exit(0);
        } catch (ClassNotFoundException e) {
            System.err.println(\"Socket Exception: peer sent bad input.\");
        }
        return null;
    }

    private String readConsoleMessage() {
        try {
            if (console_bis.available() > 0)
                return scanner.nextLine();
        } catch (IOException e) {
        }
        return null;
    }

    private void sendMessage(String message) {
        try {
            oos.reset();
            oos.writeObject(message);
            oos.flush();
        } catch (IOException e) {
            System.err
                    .println(\"Fatal Socket Exception: could not send message.\");
            System.exit(0);
        }
    }

    private void logMessage(String message, boolean display) {
        try {
            if (display) {
                System.out.println(\">> \" + message);
                bfw.append(\">> \");
            } else
                bfw.append(\"<< \");
            bfw.append(message).append(\"\\n\");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2 comments:

  1. Why is the code in Server and Client the same?

    ReplyDelete
  2. You are correct, they should be different. The client should use the IP address and port number of the server (127.0.0.0 and 3000 for testing purposes) to open a socket. Then it can simple construct a Chatter object with that socket. Sorry for the misunderstanding.

    ReplyDelete