簡體   English   中英

向所有客戶端發送消息(客戶端 - 服務器通信)

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

所以現在,我正在制作一個基於多線程的客戶端服務器應用程序。 在服務器端,我為接受的單獨連接創建了一個線程。

在線程類中,我創建了一個向客戶端發送命令的方法。 我只想要的是,如何向所有正在運行的客戶端發送參數? 對於簡單的聲明,我只想讓這個服務器向所有連接的客戶端發送消息。

我已閱讀此帖並從此鏈接中找到sendToAll(String message)方法。 但是當我嘗試使用我的代碼時,在ServerSocket沒有類似的方法。

好的,這是我的服務器和線程的示例代碼。

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) {}
}

}

感謝幫助 :)

對於完整的服務器,建議不要使用以下答案,因此您應該將Java EE與servlet,Web服務等一起使用。

這僅適用於少數計算機要連接以執行特定任務的情況,並且使用簡單的Java套接字不是一般問題。 想想分布式計算或多人游戲。

編輯:我 - 從第一篇文章 - 大大更新了這個架構,現在測試和線程安全。 任何需要它的人都可以在這里下載。

只需使用(直接或通過子類化) ServerClientstart()它們,一切就緒。 閱讀內聯注釋以獲得更強大的選項。


雖然客戶之間的溝通相當復雜,但我會盡量簡化它。

以下是服務器中的要點:

  • 保留已連接客戶端的列表。
  • 為服務器輸入定義一個線程。
  • 定義接收消息的隊列。
  • 一個線程從隊列中輪詢,並使用它。
  • 一些用於發送消息的實用方法。

對於客戶:

  • 為客戶端輸入定義一個線程。
  • 定義接收消息的隊列。
  • 一個線程從隊列中輪詢,並使用它。

這是Server類:

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);
    }

}

這里是Client類:

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);
    }
}

服務器套接字中沒有方法可以向所有正在運行的clinet線程發送數據或消息。 ServerThread.java調用sendToAll usng服務器的ServerThread.java程序。

// ... and have the server send it to all clients
server.sendToAll( message );

查看zeroMQ。 有一些稱為“pub sub”或“publish subscribe”的方法可以滿足您的需求。 您還可以使用它在線程之間進行通信。 在我看來,這是一個了不起的圖書館。 它有java或jzmq綁定以及超過30多個其他綁定,所以你應該能夠在你的程序中使用它。

http://www.zeromq.org/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM