Divya Project
Divya Project
to keep track the names and threads of the connected clients. Set is used because it
doesn’t allow duplication and the order of elements does not matter:
An important method in the ChatServer class is broadcast() which deliver a message from one client
to all others clients:
1void broadcast(String message, UserThread excludeUser) {
2 for (UserThread aUser : userThreads) {
3 if (aUser != excludeUser) {
4 aUser.sendMessage(message);
5 }
6 }
7}
The UserThread class is responsible for reading messages sent from the client and
broadcasting messages to all other clients. First, it sends a list of online users to the new
user. Then it reads the username and notifies other users about the new user.
The following code is of the UserThread class:
1 package net.codejava.networking.chat.server;
2
3
import java.io.*;
4
5 import java.net.*;
6 import java.util.*;
7
8
/**
9
1 * This thread handles connection for each connected client, so the
0 server
1
1 * can handle multiple clients at the same time.
1 *
2 * @author www.codejava.net
1
3 */
1 public class UserThread extends Thread {
4
private Socket socket;
1
5 private ChatServer server;
1 private PrintWriter writer;
6
1
public UserThread(Socket socket, ChatServer server) {
7
1 this.socket = socket;
8 this.server = server;
1
9 }
2
0
public void run() {
2
1 try {
2 InputStream input = socket.getInputStream();
2
BufferedReader reader = new BufferedReader(new
2
3 InputStreamReader(input));
2
4 OutputStream output = socket.getOutputStream();
2
5 writer = new PrintWriter(output, true);
2
6 printUsers();
2
7 String userName = reader.readLine();
2
8 server.addUserName(userName);
2
9 String serverMessage = "New user connected: " + userName;
3
server.broadcast(serverMessage, this);
0
3
1 String clientMessage;
3
2 do {
3
clientMessage = reader.readLine();
3
3 serverMessage = "[" + userName + "]: " +
4 clientMessage;
3
5 server.broadcast(serverMessage, this);
3
6 } while (!clientMessage.equals("bye"));
3
7 server.removeUser(userName, this);
3
8 socket.close();
3
9 serverMessage = userName + " has quitted.";
4
server.broadcast(serverMessage, this);
0
4
1 } catch (IOException ex) {
4 System.out.println("Error in UserThread: " +
2
ex.getMessage());
4
3 ex.printStackTrace();
4 }
4
4 }
5
4
/**
6
4 * Sends a list of online users to the newly connected user.
7 */
4
void printUsers() {
8
4 if (server.hasUsers()) {
9 writer.println("Connected users: " +
5
0 server.getUserNames());
5 } else {
1 writer.println("No other users connected");
5
2 }
5 }
3
5
/**
4
5 * Sends a message to the client.
5 */
5
void sendMessage(String message) {
6
5 writer.println(message);
7 }
5
8 }
5
9
6
0
6
1
6
2
6
3
6
4
6
5
6
6
6
7
6
8
6
9
7
0
7
1
7
2
7
3
7
4
7
5
7
6
7
7
Then it enters a loop of reading message from the user and sending it to all other users, until the user
sends ‘bye’ indicating he or she is going to quit. And finally it notifies other users about the
disconnection of this user and closes the connection.
package net.codejava.networking.chat.client;
import java.io.*;
import java.net.*;
/**
* This thread is responsible for reading server's input and printing it
* to the console.
* It runs in an infinite loop until the client disconnects from the server.
*
* @author www.codejava.net
*/
public class ReadThread extends Thread {
private BufferedReader reader;
private Socket socket;
private ChatClient client;
public ReadThread(Socket socket, ChatClient client) {
this.socket = socket;
this.client = client;
try {
InputStream input = socket.getInputStream();
reader = new BufferedReader(new InputStreamReader(input));
} catch (IOException ex) {
System.out.println("Error getting input stream: " + ex.getMessage());
ex.printStackTrace();
}
}
public void run() {
while (true) {
try {
String response = reader.readLine();
System.out.println("\n" + response);
// prints the username after displaying the server's message
if (client.getUserName() != null) {
System.out.print("[" + client.getUserName() + "]: ");
}
} catch (IOException ex) {
System.out.println("Error reading from server: " + ex.getMessage());
ex.printStackTrace();
break;
}
}
}
}
And the WriteThread is responsible for reading input from the user and sending it to the
server, continuously until the user types ‘bye’ to end the chat. This class is implemented as
follows:
package net.codejava.networking.chat.client;
import java.io.*;
import java.net.*;
/**
* This thread is responsible for reading user's input and send it
* to the server.
* It runs in an infinite loop until the user types 'bye' to quit.
*
* @author www.codejava.net
*/
public class WriteThread extends Thread {
private PrintWriter writer;
private Socket socket;
private ChatClient client;
public WriteThread(Socket socket, ChatClient client) {
this.socket = socket;
this.client = client;
try {
OutputStream output = socket.getOutputStream();
writer = new PrintWriter(output, true);
} catch (IOException ex) {
System.out.println("Error getting output stream: " + ex.getMessage());
ex.printStackTrace();
}
}
public void run() {
Console console = System.console();
String userName = console.readLine("\nEnter your name: ");
client.setUserName(userName);
writer.println(userName);
String text;
do {
text = console.readLine("[" + userName + "]: ");
writer.println(text);
} while (!text.equals("bye"));
try {
socket.close();
} catch (IOException ex) {
System.out.println("Error writing to server: " + ex.getMessage());
}
}
}
The reasons for running these two threads simultaneously is that the reading operation always blocks
the current thread (both reading user’s input from command line and reading server’s input via
network). That means if the current thread is waiting for the user’s input, it can’t read input from the
server.
Therefore, two separate threads are used to make the client responsive: it can display messages from
other users while reading message from the current user.