在JavaFX的客户端服务器聊天应用程序中向所有人发送消息

时间:2018-10-17 10:08:00

标签: sockets javafx hashmap hashtable serversocket

我能够向连接到服务器的客户端发送消息,但是

  1. 当客户兔子向乔尔发送消息(接收消息)时,反之亦然。
  2. 第二次Bunny向Joel发送消息(不接收消息)。

如何再次迭代哈希表循环以发送和接收消息。

服务器类

import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress  
import java.util.Date; //to get date
import java.util.Enumeration; //enumeration
import java.util.Hashtable; // hashtable
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close

public class Server extends Application { //class server

    static InetAddress inetAddress; //inetaddress
    private final Hashtable<Object, Object> outputStreams = new Hashtable(); //hashtable
    TextArea textarea = new TextArea(); //textarea
    static DataInputStream inputFromClient = null; //datainputstream
    static DataOutputStream outputToClient = null; //dataoutputstream
    static int clientNo = 0; //client connected
    static ServerSocket serverSocket; //server socket
    Hashtable<Object, Object> hmap = new Hashtable<>();

    @Override // Override the start method in the Application class
    public void start(Stage primaryStage) { //Stage to show everything

        StackPane root = new StackPane();        //root add all the elements
        root.setPadding(new Insets(10, 10, 10, 10)); //padding
        root.setAlignment(textarea, Pos.CENTER); //positioning textarea to center
        textarea.setMaxSize(400, 400); //maxsize of textarea
        textarea.setWrapText(true); //wraptext for the textarea

        new Thread(() -> { //thread to hold the server for the connections
            try {
                // Create a server socket
                ServerSocket serverSocket = new ServerSocket(8001); //The server creates a server socket and, once a connection to a client is established, connects to the client with a client socket.
                textarea.appendText("MultiThreadServer started at " + new Date() + '\n'); //server started with date.

                while (true) { //accept multiple connections

                    // Listen for a new connection request
                    Socket socket = serverSocket.accept(); //listening for new connection from server port.
//                    inputFromClient = new DataInputStream(socket.getInputStream());
                    outputToClient = new DataOutputStream(socket.getOutputStream()); //outputstream to output to client
                    // Increment clientNo
                    clientNo++;

                    Platform.runLater(() -> {
                        // Display the client number
                        textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');

                        // Find the client's host name, and IP address
                        InetAddress inetAddress = socket.getInetAddress();
                        textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
                        textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
                    });

                    HandleAClient hd = new HandleAClient(socket);
                    hmap.put(socket, outputToClient);
                    hd.start();
//                    outputStreams.put(socket, outputToClient); //using hashtable to store client socket and outputstream

                    // Create and start a new thread for the connection
//                    new HandleAClient(this, socket);
                }
            } catch (IOException ex) {
                textarea.appendText(ex + " \n");
            }
        }).start();

        root.getChildren().addAll(textarea); // add UI elements to the root
        Scene scene = new Scene(root, 450, 400); // creating scene of size 450 width and height 500

        primaryStage.setTitle("Server"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage

        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //close scene
            @Override
            public void handle(WindowEvent t) {
                primaryStage.close();
                Platform.exit();
                System.exit(0);
            }
        });
    }

    // Used to get the output streams
    Enumeration getOutputStreams() {
        return outputStreams.elements();
    }

    // Used to send message to all clients
    void sendToAll(String message) {
        // Go through hashtable and send message to each output stream
        for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
            DataOutputStream dout = (DataOutputStream) e.nextElement();
            try {
                // Write message
                dout.writeUTF(message);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    class HandleAClient extends Thread {

        private Socket socket; // A connected socket
        private String text = "";

        /**
         * Construct a thread
         */
        public HandleAClient(Socket socket) throws IOException {
            this.socket = socket;
        }

        /**
         * Run a thread
         */
        public void run() {
            try {
                // Create data input stream
                inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client

                textarea.appendText(new Date() + " Connection from  " + socket + "\n");//showing connection from client

                text = inputFromClient.readUTF(); // read string or message from client

//                serversocket.sendToAll(text); 
                Set set = hmap.entrySet();
                Iterator it = set.iterator();
                while (it.hasNext()) {
                    Map.Entry entry = (Map.Entry) it.next();
                    System.out.println("key " + entry.getKey() + " : " + entry.getValue());
                    DataOutputStream dout = (DataOutputStream) entry.getValue();
                    dout.writeUTF(text);
                    dout.flush();
                }

                Platform.runLater(() -> {
                    textarea.appendText(new Date() + "         " + text + "\n");//append text
                });

            } catch (IOException e) {
                textarea.appendText("Error " + e + " \n");
                try {
                    this.socket.close(); //socket close
                } catch (IOException ex) {
                    textarea.appendText("Error " + e + "  \n");
                }
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
        launch(args);
    }
}



Client Class

import java.io.*; //Input and output to read and write data.
import java.net.*; //serversocket and initaddress  
import javafx.application.Application; //
import javafx.application.Platform; //platformrun later to append text
import javafx.event.EventHandler; // on click actions
import javafx.geometry.Insets; //insets
import javafx.geometry.Pos; //position
import javafx.scene.Scene; //scene
import javafx.scene.control.TextArea; //textarea
import javafx.scene.layout.StackPane; //stackpane
import javafx.stage.Stage; //stage
import javafx.stage.WindowEvent; //event close

import javafx.scene.control.Button; // button
import javafx.scene.control.Label; //label
import javafx.scene.control.TextField; //textfield

public class Client extends Application {

    // IO streams
    static DataOutputStream toServer = null; //datainputstream
    static DataInputStream fromServer = null; //dataoutputstream
    Label usernamelabel = new Label("Set your name :"); //set name label
    Label textarealabel = new Label("Type your message in the textarea"); //text label
    Label textlabel = new Label("Enter Text :"); //enter text
    TextField textfield = new TextField(); //textfield
    TextField namefield = new TextField(); //name field
    Button send = new Button("Send"); //sendbutton
    TextArea messagefield = new TextArea(); //textarea
    static ServerSocket serverSocket; //serversocket

    // Override the start method in the Application class
    public void start(Stage primaryStage) throws IOException {

        StackPane root = new StackPane(); //stacpane
        root.setPadding(new Insets(10, 10, 10, 10));

        StackPane.setAlignment(usernamelabel, Pos.TOP_LEFT);
        namefield.setMaxWidth(200);
        StackPane.setAlignment(namefield, Pos.TOP_CENTER);

        StackPane.setMargin(textlabel, new Insets(30, 0, 0, 0));
        StackPane.setMargin(textfield, new Insets(30, 0, 0, 0));
        StackPane.setAlignment(textlabel, Pos.TOP_LEFT);
        textfield.setMaxWidth(200);
        StackPane.setAlignment(textfield, Pos.TOP_CENTER);

        StackPane.setAlignment(send, Pos.BOTTOM_CENTER);
        messagefield.setMaxSize(450, 250);
        StackPane.setAlignment(textarealabel, Pos.BOTTOM_CENTER);
        StackPane.setMargin(textarealabel, new Insets(0, 0, 35, 0));
        StackPane.setAlignment(messagefield, Pos.CENTER);

        root.getChildren().addAll(usernamelabel, namefield, send, messagefield, textarealabel, textlabel, textfield); //adding all the UI elements

        // Create a scene and place it in the stage
        Scene scene = new Scene(root, 500, 400);
        primaryStage.setTitle("Client"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage

        send.setOnAction(e -> { //send button action
            try {
                if (namefield.getText().trim().length() == 0) { //name field is empty
                    messagefield.appendText("Name field is empty. Please enter your name\n");
                } else if (textfield.getText().trim().length() == 0) { //message field is empty
                    messagefield.appendText("Message field is empty. Please enter your message to send\n");
                }
                // Send the radius to the server
                if (namefield.getText().trim().length() > 0 && textfield.getText().trim().length() > 0) {
                    toServer.writeUTF(namefield.getText().trim() + " : " + textfield.getText().trim());
                    toServer.flush();
                }

            } catch (IOException ex) {
                messagefield.appendText(ex+"   \n");
            }
        });

        try {
            // Create a socket to connect to the server
            Socket socket = new Socket("localhost", 8001); //socket with port number to connect server

            // Create an output stream to send data to the server
            toServer = new DataOutputStream(socket.getOutputStream());
            new ReceiveMessage(socket); // send socket receieve class
//            }
        } catch (Exception ex) {
            messagefield.setText(ex.toString() + '\n');
        }

        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { //scene close
            @Override
            public void handle(WindowEvent t) {
                Platform.exit();
                System.exit(0);
            }
        });
    }

    class ReceiveMessage implements Runnable { //class receive message

        private final Socket socket;//socket

        public ReceiveMessage(Socket socket) { // constructor
            this.socket = socket; //socket intializes
            Thread thread = new Thread(this);
            thread.setDaemon(true);
            thread.start();
        }

        public void run() {
            try {
                fromServer = new DataInputStream(socket.getInputStream()); //to read from server
                while (true) { // to continously receieve messages
                    // Get area from the server
                    String textmessage = fromServer.readUTF(); //read message from server
                    toServer.flush(); // flush
                    Platform.runLater(() -> {
                        messagefield.appendText(textmessage + " \n"); //append to textarea
                    });
                }
            } catch (IOException e) {
                messagefield.appendText("Error " + e);
            }
        }
    }

    public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
        launch(args);
    }
}

服务器类已执行并接受客户端

Server Class

客户端一连接

Running Client one

客户端两个已连接

Client two connected

谢谢。

1 个答案:

答案 0 :(得分:0)

我在代码中犯的错误是在客户端将消息发送到服务器并将消息发送到连接到该服务器的所有客户端之后,该服务器连接被暂停或暂停后,我不知道为什么。我使用枚举方法将消息发送到连接到服务器的所有客户端。这就是我解决问题的方式。希望我的回答对尝试使用线程实现客户端-服务器(多个客户端)聊天应用程序的人有所帮助。

import java.io.*; 
import java.net.*; 
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration; 
import java.util.Hashtable; 
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javafx.application.Application;
import javafx.application.Platform; 
import javafx.event.EventHandler;
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage; 
import javafx.stage.WindowEvent; 

public class Server extends Application { 

    static InetAddress inetAddress; 
    private final Hashtable<Object, Object> outputStreams = new Hashtable(); 
    TextArea textarea = new TextArea(); 
    static int clientNo = 0; 
    static ServerSocket serverSocket; 
    Hashtable<Object, Object> hmap = new Hashtable<>();
    ArrayList<Object> clients = new ArrayList<Object>();


    public void start(Stage primaryStage) {

        StackPane root = new StackPane(); 
        root.setPadding(new Insets(10, 10, 10, 10)); 
        root.setAlignment(textarea, Pos.CENTER);
        textarea.setMaxSize(400, 400); 
        textarea.setWrapText(true); 

        root.getChildren().addAll(textarea); 
        Scene scene = new Scene(root, 450, 400); 

        primaryStage.setTitle("Server"); 
        primaryStage.setScene(scene);
        primaryStage.show(); // Display the stage

        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() { 
            @Override
            public void handle(WindowEvent t) {
                primaryStage.close();
                Platform.exit();
                System.exit(0);
            }
        });

        new Thread(() -> {
            listen();
        }).start();
    }

    private void listen() {

        try {
            // Create a server socket
            serverSocket = new ServerSocket(8001); 
            textarea.appendText("MultiThreadServer started at " + new Date() + '\n'); 

            while (true) { 

                Socket socket = serverSocket.accept(); 
      inputFromClient = new DataInputStream(socket.getInputStream());
                DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream()); 
                clientNo++;

                Platform.runLater(() -> {

                    textarea.appendText("Starting thread for client " + clientNo + " at " + new Date() + '\n');


                    InetAddress inetAddress = socket.getInetAddress();
                    textarea.appendText("Client " + clientNo + "'s host name is " + inetAddress.getHostName() + "\n");
                    textarea.appendText("Client " + clientNo + "'s IP Address is " + inetAddress.getHostAddress() + "\n");
                });

                hmap.put(socket, outputToClient);
                new HandleAClient(socket);

            }
        } catch (IOException ex) {
            textarea.appendText(ex + " \n");
        }

    }


    Enumeration getOutputStreams() {
        return hmap.elements();
    }


    void sendToAll(String message) {

        for (Enumeration e = getOutputStreams(); e.hasMoreElements();) {
            DataOutputStream dout = (DataOutputStream) e.nextElement();
            try {

                dout.writeUTF(message);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    void All(String text) throws IOException {
        Set set = hmap.entrySet();
        Iterator it = set.iterator();
        System.out.println("Text " + text);
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            System.out.println("key " + entry.getKey() + " : " + entry.getValue());
            DataOutputStream dout = (DataOutputStream) entry.getValue();
            dout.writeUTF(text);
            dout.flush();
        }
    }

    class HandleAClient extends Thread {

        private final Socket socket; // A connected socket
        private String text = "";

        /**
         * Construct a thread
         */
        public HandleAClient(Socket socket) throws IOException {
            this.socket = socket;
            start();
        }

        /**
         * Run a thread
         */
        public void run() {
            try {

                DataInputStream inputFromClient = new DataInputStream(socket.getInputStream()); //receive input from client
                while (true) {

                    textarea.appendText(new Date() + " Connection from  " + socket + "\n");

                    text = inputFromClient.readUTF(); 

             serversocket.sendToAll(text); 
                    All(text);

                    Platform.runLater(() -> {
                        textarea.appendText(new Date() + "         " + text + "\n");
                    });
                }

            } catch (IOException e) {
                textarea.appendText("Error " + e + " \n");
                try {
                    this.socket.close();
                } catch (IOException ex) {
                    textarea.appendText("Error " + e + "  \n");
                }
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) { //The keyword void simply tells the compiler that main( ) does not return a value.
        launch(args);
    }
}