user7179690
user7179690

Reputation: 1123

simple multi-threaded server chat using java

I'm creating a java chat server that handles multi clients I use this simple code for server

public class Server extends Thread {
    ServerSocket serverSocket = null;
    Socket socket = null;
    private int unique_id;
    ArrayList<Clients> cl;


    public Server(int port) {
        try { 
            serverSocket = new ServerSocket(port);
            cl = new ArrayList<>();
            this.start();
        } catch (Exception e){
            System.out.println("Error 5");
            e.printStackTrace();
        }
    }
    @Override
    public void run(){
        System.out.println("Server Start");
            while (true){
                try {
                    socket = serverSocket.accept();
                    Clients t = new Clients(socket); // add it to thread
                    cl.add(t);
                    t.start();
                    System.out.println("Connected " + String.valueOf(cl.size())); // printed ok 
                }catch (Exception e){
                    System.out.println("Error 4");
                    e.printStackTrace();
                }
            }
    }
    public synchronized void SendToAll(String s){ // this function used by client when one of client socket send a message then server send it to all
        System.out.println("Sended is excuted"); // excuted normal each time i send a message from client but not send to all  
        for (int i = 0; i < cl.size(); i++){
            cl.get(i).WriteToSocket(s);
        }
    }

    public static void main(String args[]){
        int port = 5002;
        Server server = new Server(port); // start server
        //server.run(); // start connections wait for it
    }

    class Clients extends Thread { // class extends thread
        public Socket socket = null;
        DataInputStream input = null; // read input
        DataOutputStream output = null; // read output
        public int myid = 0; // unique id for each client

        public Clients(Socket soc) {
            socket = soc;
            try {
                input = new DataInputStream(socket.getInputStream());
                output = new DataOutputStream(socket.getOutputStream());
                myid = ++unique_id;
                System.out.println("Client Start Thread"); // printed ok !
            } catch (IOException e){
                System.out.println("Error 1");
                e.printStackTrace();
            }
        }
        public void WriteToSocket(String s) { // used to write a message to this socket
            try {
                output.write(s.getBytes());
            }catch (IOException e){
                System.out.println("Error 2");
                e.printStackTrace();
            }
        }
        @Override
        public void run() { // run thread function wait for messages from clients 
            while (true){
                try {
                    String s = input.readLine();
                    if (s.contains("quite")) {
                        socket.close();
                        input.close();
                        output.close();
                        cl.remove(this);
                        this.stop();
                    }
                    if (!s.isEmpty()) {
                        SendToAll(s);// when message come and not empty it use server function to send them to all clients 
                    }
                }catch (IOException e){
                    System.out.println("Error 3");
                    e.printStackTrace();
                }
            }
        } 
    }
}

everything works fine when clients connect the server accept the connection and the client thread started
but the problem when I sent a message from the client it didn't received by the server I try my client application in java too with Qt c++ server and it works ? so what did I do wrong here make the server can't receive the message ? this my first time in network programming using java
Edit
I solve the NullPointerException the problem was that when client log out I didn't remove his socket from the ArrayList solved by making client before close send message contains quite so when I see it i remove his socket from array list
Another Quetiosn
Here i don't know how this message sent
the System.out.println() that is in the SendToAll function printed to the screen each time client send a message but why the message not send again to all clients ?
actually the main problem is that server can't send the message to all clients in the array list after message comes from one client the problem not solved stell found
Client Code class

public class ClientSocket extends Thread {
    public Socket socket = null;
    public DataInputStream input = null;
    public DataOutputStream output = null;
    MainChat chat = null;

    public ClientSocket(String ip, int port,MainChat ch) {
        try {
            socket = new Socket(ip,port);
            input = new DataInputStream(socket.getInputStream());
            output = new DataOutputStream(socket.getOutputStream());
            chat = ch;
            this.start();
        }catch (IOException e){

        }
    }
    @Override
    public void run() {
        while (true){
            try {
                String s = input.readLine();
                if (!s.isEmpty()){
                   chat.WriteToScreen(s.trim());
                }
            }catch (IOException e){

            }
        }
    }
    public void WriteToSocket(String s) throws IOException{
        output.write(s.getBytes());
    }

}

Edit
when i use this code in main the SendToAll function send the message to all clients !! why when i use it from clients class using Thread it not sended to all ?

public static void main(String args[]){
    int port = 5002;
    Server server = new Server(port); // start server
    //server.run(); // start connections wait for it
    while (true) {
        String s = in.next();
        server.SendToAll(s + "\n"); // message sended to all client !!
    }
}

Upvotes: 1

Views: 1946

Answers (2)

rodolk
rodolk

Reputation: 5907

The problem is that readLine reads until it finds a line terminator of end of file. This is why it works with other server in QT C++ but not with the Java server. Please see here: https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readLine() https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readLine()

Please note that readLine in DataInputStream is deprecated. You should use BufferedReader to read a line (with readLine) as indicated in the DataInputStream link.

So, add '\n' to the end of the string sent and it will work.

Upvotes: 1

user7179690
user7179690

Reputation: 1123

I solve the problem, I am sorry for that it was my fault I forget to add \n in sendToAll function so this what cause the problem so no \n the clients can't read the line because I use readLine in DataInputStream
anyway I try another method to read bytes instead of readLine it's I think it's better especially when you receive UTF-8 char and after that changes from bytes to String

Upvotes: 0

Related Questions