3

I have simple server-clients programm:

public class Server extends Thread {
    private ServerSocket server;

    public Server(int port) {
        try {
            this.server = new ServerSocket(port);
            System.out.println("New server initialized!");
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while (true) {
            try {
                Socket client = server.accept();
                System.out.println(client.getInetAddress().getHostName()
                        + " connected");
                new ServerHandler(client);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Server handler must send message in stream:

public class ServerHandler extends Thread {
    protected Socket client;
    protected String userInput;
    protected PrintWriter out;
    protected BufferedReader console;

    public ServerHandler(Socket client) {
        this.client = client;
        this.userInput = null;
        this.start();
    }

    public void run() {
        System.out.println("New Communication Thread Started");
        System.out.println("Enter message:");
        try {
            this.out = new PrintWriter(client.getOutputStream(), true);
            this.console = new BufferedReader(new InputStreamReader(System.in));
            while ((this.userInput = console.readLine()) != null) {
                this.out.println(userInput);
            }               
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Client side receives that message :

public class Client {
    protected Socket client;
    protected BufferedReader in;

    public Client(String hostName, int ip) {
        try {
            this.client = new Socket(hostName, ip);
            this.in = new BufferedReader(new InputStreamReader(
                    this.client.getInputStream()));
            String buffer = null;
            while ((buffer = in.readLine()) != null) {
                System.out.println(buffer);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

It works well with one client,but when I start new client problem with receiving message from server arises. What am I doing wrong?

5
  • Not sure if this is related to your problem, but in your Server class you create a new instance of ServerHandler but you don't assign it to anything. With nothing referencing it it can be garbage collected at any time. Commented Aug 3, 2015 at 12:09
  • you need in your server an arraylist of socket connections. put each client on a thread and then create a thread in your server that sends data to your clients. make sure you synchronize on your arraylist tho Commented Aug 3, 2015 at 14:30
  • @JohnSheridan That's not correct. It extends Thread, and its constructor calls start(), so it isn't elegible for GC until it exits. Commented Aug 4, 2015 at 9:30
  • @EJP You're absolutely right. Must have been sleepwalking. Forgot that a running Thread is treated as a GC root and immune from GC. Thanks for picking this up. Commented Aug 4, 2015 at 11:45
  • 1
    Changed my code but still have problem.Read my answer below please. Commented Aug 4, 2015 at 14:55

1 Answer 1

6

I found the answer:

public class Server extends Thread {
    private ServerSocket server;
    protected List<ClientHandler> clients;

    public Server(int port) {
        try {
            this.server = new ServerSocket(port);
            System.out.println("New server initialized!");
            clients = Collections
                    .synchronizedList(new ArrayList<ClientHandler>());
            this.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void run() {
        while (true) {
            try {
                Socket client = server.accept();
                System.out.println(client.getInetAddress().getHostName()
                        + " connected");
                ClientHandler newClient = new ClientHandler(client);
                clients.add(newClient);
                new SendMessage(clients);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

ClientHandler instead of Serverhandler class:

public class ClientHandler {
    protected Socket client;
    protected PrintWriter out;

    public ClientHandler(Socket client) {
        this.client = client;
        try {
            this.out = new PrintWriter(client.getOutputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Thread can be added to Client class but works fine without it.I assume because when main method called new thread automatically created:

public class Client {
    protected Socket client;
    protected BufferedReader in;

    public Client(String hostName, int ip) {
        try {
            this.client = new Socket(hostName, ip);
            this.in = new BufferedReader(new InputStreamReader(
                    this.client.getInputStream()));
            String buffer = null;
            while ((buffer = in.readLine()) != null) {
                System.out.println(buffer);
            }
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }       
}

Class that sends data to clients:

 public class SendMessage extends Thread {
        protected List<ClientHandler> clients;
        protected String userInput;
        protected BufferedReader console;

        public SendMessage(List<ClientHandler> clients) {
            this.clients = clients;
            this.userInput = null;
            this.start();
        }

        public void run() {
            System.out.println("New Communication Thread Started");
            if (clients.size() == 1) {
                System.out.println("Enter message:");
            }
            try {
                if (clients.size() > 0) {
                    this.console = new BufferedReader(new InputStreamReader(
                            System.in));
                    while ((this.userInput = console.readLine()) != null) {
                        if (userInput != null & userInput.length() > 0) {
                            for (ClientHandler client : clients) {
                                client.out.println(userInput);
                                client.out.flush();
                            Thread.currentThread();
                            Thread.sleep(1 * 1000);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Now it works! Need to make SendMessage thread sleep after flushing data. Main for server starter:

public static void main(String[] args) {
new Server(1200);
}

Main for client starter:

public static void main(String[] args) {
new Client("127.233.0.1", 1200);
}
Sign up to request clarification or add additional context in comments.

2 Comments

If anyone needs working version I can give bitbucket link
Did it long time ago. Here is the link

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.