3
votes

I created a simple chat server that writes to all clients that is connected (I posted just the core code for simplicity)

public class server extends Thread {

private Socket clientSocket;
private static ArrayList<Socket> sockets = new ArrayList<Socket>();

public server(Socket clientSocket) {
    this.clientSocket = clientSocket;
    sockets.add(clientSocket);
}

public void run() {
    while (true) {
        try {
            for(Socket s: sockets) {
            //write something
            //the for loop will send it to every socket in the array
            }
        } catch (Exception e) {
            //catch it
        }   
    }    
}
}   

Now I want to be more specific in what client I want to send the message to, just like how a real-world chat application will have different chat rooms.

So if Client1 connects to the server, he will want to start a chat group named "Apple". And then when Client2 and Client3 connects, they can choose to join the group "Apple". Simultaneously, Client 4 will connect to the server and create another chat group called "Banana" where other clients can join in and talk there.

My understanding is that I need to somehow identify each client that the server accepts (I have no idea how to implement this). Then do I somehow put them all into their own array based on their group chat name?

I've been searching for the past week sample codes that allow more than 1 group chat simultaneously but everything I've seen just caters towards 1 only.

2
Hi @Pam, have you done some other test? - SimoV8

2 Answers

1
votes

The simplest solution is to use and hashmap with key = name of the room and value = a list of users in the chat. In practice:

HashMap<String, ArrayList<Socket>> rooms = new HashMap<>();

When a new user connects, it shoud send a message with the name of the room he want joint and after that you can check if the room already exist or not:

ArrayList<Socket> clientsList = rooms.get(roomName);
if(clientsList == null) {
    clientsList = new ArrayList<Socket>();
    rooms.put(roomName, clientsList);
}
clientsList.add(socket);

Another good idea could be to create a Client class that contains the Socket along with other information (e.g the username).

0
votes

For performance aspect I suggest you to have a look at Java nio, nio2. With nio you can handle connections in async way and dont waste 1 thread per connection. Standart socket impelementation has some drawbacks.

As solution to your problem, I'd prefer to seperate header and content of a message sent/received. In header there will be source user, target user/group,etc information. Your client will understand and print messages into related chat windows with correct sender.

On server side, you may have Users map which key is userName and value is User Object. ChatGroups map which key is groupName and value is list of user names. Since relation is many to many you need to keeps a user's all participated groups as well. Either put a groupNameList in User Object or define a seperate map.

Listen client sockets onClose action (possible with nio) and remove user from groups or maps with ablocking mechanism (concurrency)

Also adding new group, user, etc needs thread concurrency as well.