【问题标题】:How can a server broadcast a message to other clients?服务器如何向其他客户端广播消息?
【发布时间】:2019-09-30 06:37:53
【问题描述】:

该程序旨在让多个客户端连接到单个服务器,并且客户端能够在其他客户端之间发送和接收消息。

例如,如果客户端 A 说“Hi”,连接到服务器的客户端 B 和客户端 C 也会收到“Hi”。

在我当前的代码中,服务器只接收客户端发送的消息。 我目前正在寻找一种解决方案,让服务器将客户端(例如 ClientA)发送的消息广播给其他客户端。任何建议将不胜感激。

这个服务器类使用线程处理多个客户端的连接:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

class EchoThread extends Thread {
    private Socket socket;

    //constructor
    public EchoThread(Socket clientSocket) {
        this.socket = clientSocket;
    }

    @Override
    public void run() {
        DataInputStream inp = null;

        try {
            inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

            //print whatever client is saying as long as it is not "Over"
            String line = "";
            while (!line.equals("Over")) {
                try {
                    line = inp.readUTF();
                    System.out.println(line);
                } catch (IOException e) { System.out.println(e); }
            }

            //closes connection when client terminates the connection
            System.out.print("Closing Connection");
            socket.close();
        } catch (IOException e) { System.out.println(e); }
    }
}

public class Server {
    private static final int PORT = 5000;

    public static void main(String args[]) {
        ServerSocket serverSocket = null;
        Socket socket = null;

        //starts the server
        try {
            serverSocket = new ServerSocket(PORT);
            System.out.println("Server started");
            System.out.println("Waiting for a client ...\n");
        } catch (IOException e) { System.out.println(e); }

        //while loop to accept multiple clients
        int count = 1;
        while(true) {
            try {
                socket = serverSocket.accept();
                System.out.println("Client " + count + " accepted!");
                count++;
            } catch (IOException e) { System.out.println(e); }

            //starts the server thread
            new EchoThread(socket).start();
        }
    }
}

这是客户端类(我有多个运行此代码的实例):

import java.net.*;
import java.io.*;

public class ClientA {
    private Socket socket = null;
    private DataInputStream input = null;
    private DataOutputStream output = null;

    public ClientA(String address, int port) {
        //establish connection
        try {
            socket = new Socket(address, port);
            System.out.println("Connected");

            //takes input from terminal
            input = new DataInputStream(System.in);

            //sends output to the socket
            output = new DataOutputStream(socket.getOutputStream());
        } catch (IOException e) { System.out.println(e); }

        //string to read message from input
        String line = "";

        //keep reading until "Over" is input
        while (!line.equals("Over")) {
            try {
                line = input.readLine();
                output.writeUTF(line);
            } catch (IOException e) { System.out.println(e); }
        }
        //close the connection
        try {
            input.close();
            output.close();
            socket.close();
        } catch (IOException e) { System.out.println(e); }
    }

    public static void main (String args[]) {
        ClientA client = new ClientA("127.0.0.1", 5000);
    }
}

请随时纠正我的代码 cmets,因为我对套接字编程还不是很熟悉。

【问题讨论】:

    标签: java multithreading sockets


    【解决方案1】:

    你做得很好。只需在 ClientA 中添加一个线程来接收消息;并将套接字客户端存储在服务器中。 事实上,当向客户端发送消息时,Server 也是一个“客户端”。

    我根据您的代码添加了一些代码。很好用,希望对你有帮助。

    class EchoThread extends Thread {
    //*****What I add begin.
    private static List<Socket> socketList = new ArrayList<>();
    //*****What I add end.
    
    private Socket socket;
    
    //constructor
    public EchoThread(Socket clientSocket) {
        this.socket = clientSocket;
        socketList.add(socket);
    }
    
    @Override
    public void run() {
        DataInputStream inp = null;
    
        try {
            inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    
            //print whatever client is saying as long as it is not "Over"
            String line = "";
            while (!line.equals("Over")) {
                try {
                    line = inp.readUTF();
                    System.out.println(line);
    
                    //*****What I add begin.
                    sendMessageToClients(line);
                    //*****What I add end.
                } catch (IOException e) { System.out.println(e); break;}
            }
    
            //closes connection when client terminates the connection
            System.out.print("Closing Connection");
            socket.close();
        } catch (IOException e) { System.out.println(e); }
    }
    
    //*****What I add begin.
    private void sendMessageToClients(String line) throws IOException {
        for (Socket other : socketList) {
            if (other == socket) {
                continue;//ignore the sender client.
            }
            DataOutputStream output = new DataOutputStream(other.getOutputStream());
            output.writeUTF(line);
        }
    }
    //*****What I add end.
    

    }

    public class ClientA {
    private Socket socket = null;
    private DataInputStream input = null;
    private DataOutputStream output = null;
    
    public ClientA(String address, int port) {
        //establish connection
        try {
            socket = new Socket(address, port);
            System.out.println("Connected");
    
            //takes input from terminal
            input = new DataInputStream(System.in);
    
            //sends output to the socket
            output = new DataOutputStream(socket.getOutputStream());
    
            //*****What I add begin.
            //Here create a thread to receive message from server.
            DataInputStream inp = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
            new Thread(() -> {
                while (true) {
                    String str;
                    try {
                        str = inp.readUTF();
                        System.out.println(str);
                    } catch (IOException e) {
                        e.printStackTrace();//error.
                        break;
                    }
                }
            }, "Client Reveiver.").start();
            //*****What I add end.
    
        } catch (IOException e) { System.out.println(e); }
    
        //string to read message from input
        String line = "";
    
        //keep reading until "Over" is input
        while (!line.equals("Over")) {
            try {
                line = input.readLine();
                output.writeUTF(line);
            } catch (IOException e) { System.out.println(e); }
        }
        //close the connection
        try {
            input.close();
            output.close();
            socket.close();
        } catch (IOException e) { System.out.println(e); }
    }
    

    【讨论】:

    • 补充一下,其实还有很多IO异常需要处理。这里只是一个非常简单的例子。 :)
    • socketList 应该是一个并发集合,因为客户端可以同时连接。在这种情况下,我建议 CopyOnWriteArrayList.
    【解决方案2】:

    我将有一个服务器线程来维护客户端的注册,可能在并发集合中。然后我将从客户端收到的每条消息发送给所有其他客户端。

    【讨论】:

      猜你喜欢
      • 2018-11-14
      • 1970-01-01
      • 2016-12-02
      • 2016-02-24
      • 1970-01-01
      • 2012-06-12
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多