diff options
| author | O'Shea <osheas1@wit.edu> | 2020-12-10 14:03:54 -0500 |
|---|---|---|
| committer | O'Shea <osheas1@wit.edu> | 2020-12-10 14:03:54 -0500 |
| commit | cca61c9f562d2c9e2be13ec16abe134d209b54e3 (patch) | |
| tree | 3f957b579c45d0536e7e1740acdb0cdbc773f9f4 /src/backend/ChatServer.java | |
| parent | 690bbba9550e2644e48db44fb94d4df86494a34e (diff) | |
Final implementation, ready for presentation!
Diffstat (limited to 'src/backend/ChatServer.java')
| -rw-r--r-- | src/backend/ChatServer.java | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/backend/ChatServer.java b/src/backend/ChatServer.java new file mode 100644 index 0000000..c8ebfef --- /dev/null +++ b/src/backend/ChatServer.java @@ -0,0 +1,309 @@ + +package backend ; + +import java.io.DataInputStream ; +import java.io.DataOutputStream ; +import java.io.IOException ; +import java.net.ServerSocket ; +import java.net.Socket ; +import java.util.ArrayList ; + +/** + * ChatServer class accepts Client requests to join + * and creates an individual thread for each client. + * The "brain" of the server. + * + * @author osheas1 + * @author gohringj + * @version Semi-Final Draft + */ +public class ChatServer + { + + // List of all active users in Server + public static ArrayList<ClientHandler> userList = new ArrayList<>() ; + + + /** + * @param args (unused) + * @throws IOException (is thrown if connection is unexpectedly closed) + */ + public static void main( final String[] args ) throws IOException + { + // Register service on port 6789 + ServerSocket serverSocket = new ServerSocket( 6789 ) ; + Socket socket = null ; + + System.out.println( "\nServer established. Awaiting connections..." ) ; + + // Loop to accept client requests + while ( true ) + { + socket = serverSocket.accept() ; + + DataOutputStream dataStreamOut = new DataOutputStream( socket.getOutputStream() ) ; + DataInputStream dataStreamIn = new DataInputStream( socket.getInputStream() ) ; + + System.out.println( "\nClient connection detected, requesting username..." ) ; + String username = dataStreamIn.readUTF() ; + + ClientHandler handle = new ClientHandler( socket, username, dataStreamOut, dataStreamIn ) ; + + System.out.println( "\nCreating new thread...\n" ) ; + Thread thread = new Thread( handle ) ; + + userList.add( handle ) ; + + thread.start() ; + } + } + } // end class ChatServer + + + + +/** + * ClientHandler class manages the actual messages being sent + * between the users. The "heart" of the server. + * + * @author osheas1 + * @author gohringj + * @version Semi-Final Draft + */ + +class ClientHandler implements Runnable + { + Socket socket ; + String username ; + DataOutputStream dataStreamOut ; + DataInputStream dataStreamIn ; + boolean loggedIn ; + int commandCheck ; + + /** + * Constructor + * @param s = client socket + * @param user = client's user-name + * @param dos = data stream to client + * @param dis = data stream from client + */ + public ClientHandler( Socket s, String user, DataOutputStream dos, DataInputStream dis ) + { + this.socket = s ; + this.username = user ; + this.dataStreamOut = dos ; + this.dataStreamIn = dis ; + this.loggedIn = true ; + } + + + @Override + public void run() + { + // Note the connection of the new user + String announcement = String.format( "\n>>> User \"%s\" has successfully connected (type /help for a list of commands) <<<\n", this.username ) ; + System.out.println( announcement ) ; + + // Distribute announcement to entire server + sendMessage( announcement ) ; + + // Message management + String message = "" ; + while ( true ) + { + // Try-Catch block interprets incoming messages + try + { + message = this.dataStreamIn.readUTF() ; + + if(message == "" || message == " ") + { + continue ; + } + } + catch ( IOException x ) + { + x.printStackTrace() ; + } + + // Check message for user commands, returns TRUE if user "/quit"s + if( commands( message, this ) ) + { + break ; + } + + // Print the message server-side + message = String.format( "%s: %s", this.username, message ) ; + System.out.println( message ) ; + + // Distribute the message to all users + if ( this.commandCheck == 0 ) + { + sendMessage( message ) ; + } + else + { + this.commandCheck = 0 ; + } + } // end while + + // close streams when user disconnects + try + { + this.loggedIn = false ; + this.dataStreamIn.close() ; + this.dataStreamOut.close() ; + this.socket.close() ; + } + catch ( IOException x ) + { + x.printStackTrace() ; + } + } // end run + + + /** + * The 'commands' method manages the usage of user-commands + * by distributing private messages, providing a user-list, + * etc. + * + * @param message = the command itself + * @param user = the user that + * @return = boolean that indicates that the user has disconnected + */ + public boolean commands( String message, final ClientHandler user ) + { + final String[] commands = new String[] { "/help", "/quit", "/userlist", "/pm" } ; + + try + { + // Quit command terminates client's connection, with an announcement + if ( message.equals( "/quit" ) ) + { + this.commandCheck++ ; + String announcement = String.format( "\n-= \"%s\" has disconnected =- \n", user.username ) ; + System.out.println( announcement ) ; + sendMessage( announcement ) ; + return true ; + } + + // User-List command provides the user a list of everyone else connected to the server + if ( message.equals( "/userlist" ) ) + { + this.commandCheck++ ; + user.dataStreamOut.writeUTF( "> Current list of users in the server: " ) ; + for ( ClientHandler users : ChatServer.userList ) + { + if ( !users.loggedIn ) + { + continue ; + } + + user.dataStreamOut.writeUTF( "> " + users.username ) ; + } + } + + // Help command lists all available commands + if ( message.equals( "/help" ) ) + { + this.commandCheck++ ; + user.dataStreamOut.writeUTF( "\n> All available commands: " ) ; + for ( String command : commands ) + { + user.dataStreamOut.writeUTF( "> " +command ) ; + } + + user.dataStreamOut.writeUTF( "\n" ) ; + } + + // Private Message Command allows users to send messages to a single recipient + if ( message.contains( "/pm" ) ) + { + this.commandCheck++ ; + user.dataStreamOut.writeUTF( "\n> Who would you like to private message?" ) ; + String recipient = this.dataStreamIn.readUTF() ; + user.dataStreamOut.writeUTF( "> \"" + recipient + "\"" ) ; + + ClientHandler sendTo = null ; + + // loop determines which ClientHandler object to send the message to + for ( ClientHandler users : ChatServer.userList ) + { + if ( !users.loggedIn ) + { + continue ; + } + else if ( users.username.equals( recipient ) ) + { + sendTo = users ; + } + } + + if ( sendTo == null ) + { + user.dataStreamOut.writeUTF( "\n> User not found, please try again" ) ; + return false ; + } + + user.dataStreamOut.writeUTF( "\n> What would you like to say?" ) ; + String privateMessage = this.dataStreamIn.readUTF() ; + user.dataStreamOut.writeUTF( "> sent: \"" + privateMessage + "\"" ) ; + sendPrivateMessage( privateMessage, user.username, sendTo ) ; + + } + } + + catch ( IOException x ) + { + while ( ChatServer.userList.size() != 0 ) + { + System.out.println( x ) ; + } + } + + return false ; + } // end commands + + + // Convenience method to send messages privately + private static void sendPrivateMessage( String message, final String sentfrom, final ClientHandler sendto ) + { + try + { + for ( ClientHandler users : ChatServer.userList ) + { + if ( users.equals( sendto ) ) + { + message = String.format( "\nFrom <%s>: %s", sentfrom, message ) ; + users.dataStreamOut.writeUTF( message ) ; + } + } + } + catch ( final IOException x ) + { + x.printStackTrace() ; + } + } + + + // Convenience method to distribute messages to all clients + private static void sendMessage( String message ) + { + try + { + for ( ClientHandler users : ChatServer.userList ) + { + if ( !users.loggedIn ) + { + continue ; + } + users.dataStreamOut.writeUTF( message ) ; + } + } + catch ( IOException x ) + { + x.printStackTrace() ; + } + } + } +// end class ClientHandler
\ No newline at end of file |
