Сервер Java / JavaFX — программа чата с несколькими клиентами

#java #multithreading #sockets #javafx #networking

#java #многопоточность #сокеты #javafx #сеть

Вопрос:

Я новичок в создании сетей на Java и пытаюсь создать серверное / клиентское приложение для чата. Ниже приведен код, который принимает один клиентский запрос, и данные отлично передаются между клиентом и сервером.

Для работы с несколькими клиентами я использовал InetAddress для приема нескольких клиентских запросов, но сервер продолжает зависать.

Хотелось бы получить помощь в выполнении функций чата на сервере / с несколькими клиентами.

Это код, над которым я работаю

Server.java

 import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
import java.util.Date;

public class Server extends Application {

    TextArea serverDetails = new TextArea();
    TextField serverTextFld = new TextField();


    @Override
    public void start(Stage stage) throws Exception {
        serverDetails.setFont(Font.font(14));
        serverDetails.setPrefHeight(550);
        serverDetails.setEditable(false);

        VBox root = new VBox(20, serverDetails, serverTextFld);
        Scene scene = new Scene(root, 500, 500);
        stage.setTitle("Server");
        stage.setScene(scene);
        stage.show();

        new Server();
    }

    public class Server implements Runnable {

        ServerSocket serversocket;
        DataInputStream  inFromClient;
        DataOutputStream outToClient;
        Socket socket;
        Thread t1, t2;
        String dataIn = "", dataOut = "";

        public Server() {
            try {
                t1 = new Thread(this);
                t2 = new Thread(this);
                serversocket = new ServerSocket(5000);
                serverDetails.appendText("Waiting for client n");
                Platform.runLater(() -> {
                    try {
                        socket = serversocket.accept();
                        t1.start();
                        t2.start();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });

                System.out.println(socket.getLocalPort());


            } catch (Exception e) {
            }
        }

        public void run() {
            try {
                if (Thread.currentThread() == t1) {
                    serverTextFld.setOnAction(e-> {
                        String userInput1 = serverTextFld.getText();
                        serverTextFld.clear();
                        try {
                            outToClient = new DataOutputStream(socket.getOutputStream());
                        } catch (IOException ioException) {
                            ioException.printStackTrace();
                        }
                        dataIn=userInput1;
                        Platform.runLater(() -> {
                            serverDetails.appendText("Server: "  userInput1   'n');
                        });
                        try {
                            outToClient.writeUTF(userInput1);
                        } catch (IOException ioException) {
                            ioException.printStackTrace();
                        }
                    });

                } else {
                    do {
                        inFromClient = new DataInputStream((socket.getInputStream()));
                        dataOut = inFromClient.readUTF();
                        serverDetails.appendText("Client: "  dataOut   'n');
                    } while (!dataOut.equals("END"));
                }
            } catch (Exception e) {
            }
        }

    }
}
  

Client.java

 import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DecimalFormat;
import java.util.Date;

public class Client extends Application {

    TextArea clientDetails = new TextArea();
    TextField clientTextFld = new TextField();

    @Override
    public void start(Stage stage) throws Exception {
        clientDetails.setFont(Font.font(14));
        clientDetails.setPrefHeight(550);
        clientDetails.setEditable(false);

        VBox root = new VBox(20, clientDetails, clientTextFld);
        Scene scene = new Scene(root, 500, 500);
        stage.setTitle("Client");
        stage.setScene(scene);
        stage.show();

        new Client();

    }

    public class Client implements Runnable {
        DataInputStream  inFromServer;
        DataOutputStream outToServer;
        Socket socket;
        Thread t1, t2;
        String dataIn = "", dataOut = "";

        public Client() {
            try {
                t1 = new Thread(this);
                t2 = new Thread(this);
                socket = new Socket("localhost", 5000);
                t1.start();
                t2.start();

            } catch (Exception e) {
            }
        }

        public void run() {

            try {
                if (Thread.currentThread() == t2) {
                    clientTextFld.setOnAction(e->{
                        String userInput1 = clientTextFld.getText();
                        clientTextFld.clear();
                        try {
                            outToServer = new DataOutputStream(socket.getOutputStream());
                        } catch (IOException ioException) {
                            ioException.printStackTrace();
                        }
                        dataIn=userInput1;
                        Platform.runLater(() -> {
                            clientDetails.appendText("Client: "  userInput1   'n');
                        });
                        try {
                            outToServer.writeUTF(userInput1);
                        } catch (IOException ioException) {
                            ioException.printStackTrace();
                        }
                    });
                } else {
                    do {
                        inFromServer = new DataInputStream((socket.getInputStream()));
                        dataOut = inFromServer.readUTF();
                        clientDetails.appendText("Server: "  dataOut   'n');
                    } while (!dataOut.equals("END"));
                }
            } catch (Exception e) {
            }

        }
    }
}
  

Комментарии:

1. Почему вы чрезмерно усложняете ситуацию, создавая сервер как графическую операцию. Я бы просто сделал его стандартным java-сервером bog. Как только он отлажен и работает, пришло время сделать его необычным.

2. Я устал от этого, но это не сильно помогло делу.

3. Вам нужно задать конкретный вопрос.

4. Один из способов обработки нескольких запросов на вашем сервере — передавать каждый запрос новому потоку.

5. Можете ли вы посоветовать, как это можно реализовать. Я использовал new Thread(() -> {}); на сервере и handleAClient(сокет), но затем связь между сервером и клиентами нарушается.