javamultithreadingserverclientchatroom

Limit number of clients that will connect through the server


I need to limit the number of client that can connect to the server . I only want 3 clients that can connect not more.

I tried if else conditions. and some loops.

public class server {

    ServerSocket ss;
    boolean quite=false;
    ArrayList<MultiServerConnection> OurDomainsConnections=new ArrayList<MultiServerConnection>();

    public static void main(String[] args) {
        new server();

    }
    public server() {
        try {
            //TODO use method to take this as an input from user)
            ss=new ServerSocket(3333);//here we are using connection 3333 (change as you want
            while(!quite)
            {
                Socket s=ss.accept();//when a connection to the domain is found we accept it
                MultiServerConnection OurConnection = new MultiServerConnection(s,this);
                OurConnection.start();//Start Thread
                OurDomainsConnections.add(OurConnection);//add connection to our Domain Connection
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }//make sure its bloody same with client it took my 15 min to realize that XD
    }
}

public class MultiServerConnection extends Thread {

    Socket s;
    DataInputStream din;
    DataOutputStream dout;
    server ss;
    boolean quite=false;

    public MultiServerConnection(Socket OurSocket,server OurServer)
    {
        super("MultiServerConnection");//server connection thread
        this.s=OurSocket;
        this.ss=OurServer;
    }

    public void ServerOutClientIn(String OutText)
    {
        try {
            long ThreadID=this.getId();
            dout.writeUTF(OutText);
            dout.flush();//this is because of a buffer error :<
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void ServerOutAllClientIn(String OutText)
    {
        for(int i=0;i<ss.OurDomainsConnections.size();i++)
        {
            MultiServerConnection Connection=ss.OurDomainsConnections.get(i);
            Connection.ServerOutClientIn(OutText);
        }
    }

    public void run()
    {
        try {
            din=new DataInputStream(s.getInputStream());
            dout=new DataOutputStream(s.getOutputStream());

            while(!quite)
            {
                while(din.available()==0)
                {
                    try {
                        Thread.sleep(1);//sleep if there is not data coming
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                String ComingText=din.readUTF();
                ServerOutAllClientIn(ComingText);
            }
            din.close();
            dout.close();
            s.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

public class MultiClients extends Thread {

    Socket s;
    DataInputStream din;
    DataOutputStream dout;
    boolean quite=false;
    public ClientData c;
    public interface1 GUI;

    public MultiClients(Socket OurMultiSocket, interface1 gui)
    {
        s=OurMultiSocket;
        c=new ClientData();
        GUI=gui;
    }
    public void ClientOutServerIn(String Text)
    {
        //write the line from console to server
        try {
            if(Text.equals("change channel"))
            {
                System.out.print("sending changing channel: "+Text+"\n");
                dout.writeUTF(Text);
                dout.flush();
            }
            else if(Text.equals("new user"))
            {
                System.out.print("sending new user: "+ Text+"\n");
                dout.writeUTF(Text+":"+c.GetName()+"="+c.GetChannel());
                dout.flush();
            }
            else
            {
                dout.writeUTF(c.GetChannel()+"="+this.getName()+": "+Text);
                dout.flush();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }   
    }
    public void SetClient(String channel,String Name)
    {
        c.SetName(Name);
        c.SetChannel(channel);
    }
    public void run()
    {
        try {
            din=new DataInputStream(s.getInputStream());
            dout=new DataOutputStream(s.getOutputStream());
            while(!quite)
            {
                try {
                    while(din.available()==0)
                    {
                        try {
                            Thread.sleep(1);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    //if there is something just show it on console
                    //and then go back and do the same
                    String reply=din.readUTF();
                    String Chan=ExtractChannel(reply);
                    String name=ExtractName(reply);
                    /*if (reply.equals("change channel"))
                    {
                        System.out.print("changing channel in body: "+reply+"\n");
                        //GUI.ClearDisplay();
                        setChangedChannel();
                    }*/
                    if(name.equals("new user"))
                    {
                        System.out.print("new user in body: "+reply+"\n");
                        //GUI.ClearDisplay();
                        setChannel(reply);
                    }
                    else
                    {
                        PrintReply(Chan,reply);
                    }
                    //System.out.println(reply);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    try {
                        din.close();
                        dout.close();
                        s.close();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }   
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            try {
                din.close();
                dout.close();
                s.close();
            } catch (IOException x) {
                // TODO Auto-generated catch block
                x.printStackTrace();
            }
        }
    }
    public void CloseClient()
    {
        try {
            din.close();
            dout.close();
            s.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public String ExtractName(String x)
    {
        String[]Y=x.split(":");
        return Y[0];
    }
    public String ExtractChannel(String X)
    {
        String[]Y=X.split("=");
        return Y[0];
    }
    public void PrintReply(String Chan,String Rep)
    {
        if(c.GetChannel().equals(Chan))
        {
            String []Y=Rep.split("=");
            GUI.setDisplay(Y[1]);
            //System.out.println(Y[1]+"\n \n \n \n");
        }

    }
    public void setChannel(String x)
    {
        String []Y=x.split(":");
        String []Z=Y[1].split("=");
        System.out.print("setting "+Z[0]+" channel to "+Z[1]+"\n");
        GUI.setUserInChannel(Z[0]);
    }
    public void setChangedChannel()
    {
        GUI.setUserInChannel(c.GetName()+": "+c.GetChannel());
    }
    class ClientData
    {
        public String ClientName;
        public String channel;

        public void SetChannel(String Chan)
        {
            channel=Chan;
        }
        public void SetName(String name)
        {
            ClientName=name;
        }
        public String GetChannel()
        {
            return channel;
        }
        public String GetName()
        {
            return ClientName;
        }
    }

}

in this code. more than 5 user can can chat together. i only want to allow 3 user to connect and to chat.


Solution

  • You can use AtomicInteger as a counter to check how many clients you have already connected:

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.concurrent.atomic.AtomicInteger;
    
    public class server {
    
        ServerSocket ss;
        boolean quite=false;
        ArrayList<MultiServerConnection> OurDomainsConnections=new ArrayList<MultiServerConnection>();
        final AtomicInteger runningCount = new AtomicInteger(0);
        final Integer limit = 3;
    
        public static void main(String[] args) {
            new server();
    
        }
        public server() {
            try {
                //TODO use method to take this as an input from user)
                ss=new ServerSocket(3333);//here we are using connection 3333 (change as you want
                while(!quite)
                {
    
                    Socket s=ss.accept();//when a connection to the domain is found we accept it
                    if (runningCount.incrementAndGet() < limit){ //increment number of clients and check
                        MultiServerConnection OurConnection = new MultiServerConnection(s,this, runningCount::decrementAndGet);
                        OurConnection.start();//Start Thread
                        OurDomainsConnections.add(OurConnection);//add connection to our Domain Connection
                    } else {
                        runningCount.decrementAndGet();
                        s.close();
                        System.out.println("limit exceeded");
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }//make sure its bloody same with client it took my 15 min to realize that XD
        }
    }
    
    interface Callback {
       void call();
    }
    
    class MultiServerConnection extends Thread {
    
        Socket s;
        DataInputStream din;
        DataOutputStream dout;
        server ss;
        boolean quite=false;
        final Callback callbackOnFinish;
    
        public MultiServerConnection(Socket OurSocket,server OurServer, Callback callbackOnFinish)
        {
            super("MultiServerConnection");//server connection thread
            this.s=OurSocket;
            this.ss=OurServer;
            this.callbackOnFinish = callbackOnFinish;
        }
    
        public void ServerOutClientIn(String OutText)
        {
            try {
                long ThreadID=this.getId();
                dout.writeUTF(OutText);
                dout.flush();//this is because of a buffer error :<
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        public void ServerOutAllClientIn(String OutText)
        {
            for(int i=0;i<ss.OurDomainsConnections.size();i++)
            {
                MultiServerConnection Connection=ss.OurDomainsConnections.get(i);
                Connection.ServerOutClientIn(OutText);
            }
        }
    
        public void run()
        {
            try {
                din=new DataInputStream(s.getInputStream());
                dout=new DataOutputStream(s.getOutputStream());
    
                while(!quite)
                {
                    while(din.available()==0)
                    {
                        try {
                            Thread.sleep(1);//sleep if there is not data coming
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    String ComingText=din.readUTF();
                    ServerOutAllClientIn(ComingText);
                }
                din.close();
                dout.close();
                s.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                callbackOnFinish.call();
            }
        }
    }
    

    When a new connection is accepted runningCount is atomically increased and value is got by runningCount.incrementAndGet(). Then if value below the limit - new MultiServerConnection is created with a callback. The callback is used for decrementing a counter on exit. If counter equal or above the limit => socket will be closed and error message printed. It is good to have a message passed to the socket.

    P.S. I have not reviewed your solution. I've just added the feture you requested.