0
votes

I need to limit the number of clients that can connect to the server . I only want 5 clients to be able to connect. When a 6th client tries to connect, he'll be added to the queue. Once one of the clients leaves, the .remove is called, it will go to the queue and fetch the first client waiting and connect him to the chat.

    public void start() {
    keepGoing = true;
    /* create socket server and wait for connection requests */
    try 
    {
        // the socket used by the server
        ServerSocket serverSocket = new ServerSocket(port);

        // infinite loop to wait for connections
        while(keepGoing) 
        {
            // format message saying we are waiting
            display("Server waiting for Clients on port " + port + ".");

            Socket socket = serverSocket.accept();      // accept connection
            // if I was asked to stop
            if(!keepGoing)
                break;
            ClientThread t = new ClientThread(socket);  // make a thread of it
            al.add(t);                                  // save it in the ArrayList
            t.start();
        }
        // I was asked to stop
        try {
            serverSocket.close();
            for(int i = 0; i < al.size(); ++i) {
                ClientThread tc = al.get(i);
                try {
                tc.sInput.close();
                tc.sOutput.close();
                tc.socket.close();
                }
                catch(IOException ioE) {
                    // not much I can do
                }
            }
        }
        catch(Exception e) {
            display("Exception closing the server and clients: " + e);
        }
    }
    // something went bad
    catch (IOException e) {
        String msg = sdf.format(new Date()) + " Exception on new ServerSocket: " + e + "\n";
        display(msg);
    }
}   

To broadcast a message to all Clients:

    private synchronized void broadcast(String message) {
    // add HH:mm:ss and \n to the message
    String time = sdf.format(new Date());
    String messageLf = time + " " + message + "\n";
    // display message on console or GUI
    if(sg == null)
        System.out.print(messageLf);
    else
        sg.appendRoom(messageLf);     // append in the room window

    // we loop in reverse order in case we would have to remove a Client
    // because it has disconnected
    for(int i = al.size(); --i >= 0;) {
        ClientThread ct = al.get(i);
        // try to write to the Client if it fails remove it from the list
        if(!ct.writeMsg(messageLf)) {
            al.remove(i);
            display("Disconnected Client " + ct.username + " removed from list.");
          }
      }
  }

For a client who logoff using the LOGOUT message:

    synchronized void remove(int id) {
    // scan the array list until we found the Id
    for(int i = 0; i < al.size(); ++i) {
        ClientThread ct = al.get(i);
        // found it
        if(ct.id == id) {
            al.remove(i);
            return;
        }
    }
}
1
You forgot to mention your problem?Mahendran Ayyarsamy Kandiar
Please give us a specific question, or at least a description of the problem.Snail Cadet
The question is: how do I add the limiter? I've been thinking about it for days but haven't been able to construct a proper code. I only want 5 clients to be able to connect to the server at the same time. And if a 6th client tries to connect, he'll have to wait in a queue until he's called once one of the 5 connected clients leaves.Pierre Ibrahim

1 Answers

1
votes

Simplest way to only accept a certain number of clients and queue the rest, is to stop listening for clients when the limit has been reached.

ServerSocket already has a queue, so if you stop listening, excessive requests are automatically queued anyway. To control the queue size, use the ServerSocket(int port, int backlog) constructor:

[...]

The maximum queue length for incoming connection indications (a request to connect) is set to the backlog parameter. If a connection indication arrives when the queue is full, the connection is refused.

[...]

Parameters:

port - the port number, or 0 to use a port number that is automatically allocated.

backlog - requested maximum length of the queue of incoming connections.

So, if the number of running Client Threads is at the limit, don't call serverSocket.accept(). Wait for a Client Thread to end before the main thread calls accept() again.

The easiest way to manage that is by using a Semaphore with the given thread limit as the number of permits, i.e. the main thread calls acquire() before calling accept(), and the Client Thread calls release() from a finally block before it ends.

Hint: You can get better performance if you use a thread pool instead of starting a new thread for each request.