Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a message to all clients (Client - Server communication)

So now, I am making a client server app based multithread. In server side, I make a thread for everysingle connection that accepted.

In thread class, I make a method that send a command to client. What i just want is, how to send a parameter to all running client? For simple statement, i just want to make this server send a message to all connected client.

I've been read this post and find sendToAll(String message) method from this link. But when i am try in my code, there is no method like that in ServerSocket .

Okay this is my sample code for server and the thread.

class ServerOne{

ServerSocket server = null;
...

ServerOne(int port){
            System.out.println("Starting server on port "+port);
    try{
      server = new ServerSocket(port);
              System.out.println("Server started successfully and now waiting for client");

    } catch (IOException e) {
      System.out.println("Could not listen on port "+port);
      System.exit(-1);
    }
}

public void listenSocket(){ 
    while(true){
        ClientWorker w;
        try{
            w = new ClientWorker(server.accept());
            Thread t = new Thread(w);
            t.start();
        } catch (IOException e) {
            System.out.println("Accept failed: 4444");
            System.exit(-1);
        }   
    }
}

protected void finalize(){
    try{
        server.close();
    } catch (IOException e) {
        System.out.println("Could not close socket");
        System.exit(-1);
    }
}
}

class ClientWorker implements Runnable{
Socket client;

ClientWorker(Socket client){
    this.client = client;
}
public void run(){
    ...
      sendCommand(parameter);
    ...
}

public void sendCommand(String command){
    PrintWriter out = null;
    try {
        out = new PrintWriter(client.getOutputStream(), true);
        out.println(command);
    } catch (IOException ex) {}
}

}

Thanks for help :)

like image 813
irvana Avatar asked Oct 29 '12 04:10

irvana


People also ask

How do you communicate with client and server?

Client-server protocols Clients typically communicate with servers by using the TCP/IP protocol suite. TCP is a connection-oriented protocol, which means a connection is established and maintained until the application programs at each end have finished exchanging messages.

How to communicate between two servers in java?

For a basic solution you can use Socket.IO if you are already using it and know how it works, it will get the job done since it allows for communication between a client and server where the client can be a different server in a different language.

How to connect two clients through server in java?

Create a thread that will handle a ServerSocket to accept connections. Make the clients send a unique identificator to the server upon connection. When a client sends a message, use the id of the desired receiver client as a parameter, or empty so send to all clients.


2 Answers

The below answer, is not recommended for a full fledged server, as for this you should use Java EE with servlets, web services etc.

This is only intended where a few computers want to connect to perform a specific task, and using simple Java sockets is not a general problem. Think of distributed computing or multi-player gaming.

EDIT: I've - since first post - greatly updated this architecture, now tested and thread-safe. Anybody who needs it may download it here.

Simply use (directly, or by subclassing) Server and Client, start() them, and everything is ready. Read the inline comments for more powerful options.


While communication between clients are fairly complicated, I'll try to simplify it, the most possible.

Here are the points, in the server:

  • Keeping a list of connected clients.
  • Defining a thread, for server input.
  • Defining a queue of the received messages.
  • A thread polling from the queue, and work with it.
  • Some utility methods for sending messages.

And for the client:

  • Defining a thread, for client input.
  • Defining a queue of the received messages.
  • A thread polling from the queue, and work with it.

Here's the Server class:

public class Server {
    private ArrayList<ConnectionToClient> clientList;
    private LinkedBlockingQueue<Object> messages;
    private ServerSocket serverSocket;

    public Server(int port) {
        clientList = new ArrayList<ConnectionToClient>();
        messages = new LinkedBlockingQueue<Object>();
        serverSocket = new ServerSocket(port);

        Thread accept = new Thread() {
            public void run(){
                while(true){
                    try{
                        Socket s = serverSocket.accept();
                        clientList.add(new ConnectionToClient(s));
                    }
                    catch(IOException e){ e.printStackTrace(); }
                }
            }
        };

        accept.setDaemon(true);
        accept.start();

        Thread messageHandling = new Thread() {
            public void run(){
                while(true){
                    try{
                        Object message = messages.take();
                        // Do some handling here...
                        System.out.println("Message Received: " + message);
                    }
                    catch(InterruptedException e){ }
                }
            }
        };

        messageHandling.setDaemon(true);
        messageHandling.start();
    }
    
    private class ConnectionToClient {
        ObjectInputStream in;
        ObjectOutputStream out;
        Socket socket;

        ConnectionToClient(Socket socket) throws IOException {
            this.socket = socket;
            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());

            Thread read = new Thread(){
                public void run(){
                    while(true){
                        try{
                            Object obj = in.readObject();
                            messages.put(obj);
                        }
                        catch(IOException e){ e.printStackTrace(); }
                    }
                }
            };

            read.setDaemon(true); // terminate when main ends
            read.start();
        }

        public void write(Object obj) {
            try{
                out.writeObject(obj);
            }
            catch(IOException e){ e.printStackTrace(); }
        }
    }

    public void sendToOne(int index, Object message)throws IndexOutOfBoundsException {
        clientList.get(index).write(message);
    }

    public void sendToAll(Object message){
        for(ConnectionToClient client : clientList)
            client.write(message);
    }

}

And here for the Client class:

public class Client {
    private ConnectionToServer server;
    private LinkedBlockingQueue<Object> messages;
    private Socket socket;

    public Client(String IPAddress, int port) throws IOException{
        socket = new Socket(IPAddress, port);
        messages = new LinkedBlokingQueue<Object>();
        server = new ConnecionToServer(socket);

        Thread messageHandling = new Thread() {
            public void run(){
                while(true){
                    try{
                        Object message = messages.take();
                        // Do some handling here...
                        System.out.println("Message Received: " + message);
                    }
                    catch(InterruptedException e){ }
                }
            }
        };

        messageHandling.setDaemon(true);
        messageHandling.start();
    }

    private class ConnectionToServer {
        ObjectInputStream in;
        ObjectOutputStream out;
        Socket socket;

        ConnectionToServer(Socket socket) throws IOException {
            this.socket = socket;
            in = new ObjectInputStream(socket.getInputStream());
            out = new ObjectOutputStream(socket.getOutputStream());

            Thread read = new Thread(){
                public void run(){
                    while(true){
                        try{
                            Object obj = in.readObject();
                            messages.put(obj);
                        }
                        catch(IOException e){ e.printStackTrace(); }
                    }
                }
            };

            read.setDaemon(true);
            read.start();
        }

        private void write(Object obj) {
            try{
                out.writeObject(obj);
            }
            catch(IOException e){ e.printStackTrace(); }
        }


    }

    public void send(Object obj) {
        server.write(obj);
    }
}
like image 96
Mordechai Avatar answered Sep 22 '22 20:09

Mordechai


There is no method in server socket to send data or message to all running clinet threads. Please go through the ServerThread.java program which is calling the sendToAll usng server.

// ... and have the server send it to all clients
server.sendToAll( message );
like image 26
UVM Avatar answered Sep 23 '22 20:09

UVM