MultiClient-Server, реализация сокетов в javaFX - PullRequest
0 голосов
/ 10 апреля 2020

Я создаю настольное приложение с javaFX. В этом приложении я должен проверить новые запросы от других клиентов к текущему пользователю; если текущий пользователь (получатель) и другой удаленный клиент (отправитель) активны, используя сокеты.

(в конце указывается сомнение)

Я постараюсь чтобы все было как можно проще.

Существует четыре класса, связанных с реализацией сокетов:

Сервер

ClientHandler

Клиент

ServerConnection

1) Сервер

public class Server {
    private static final int PORT = 9090;
    private static HashMap<String,ClientHandler> clients = new HashMap<>();

    private static ExecutorService pool = Executors.newFixedThreadPool(4);
    public static void main(String[] args) throws IOException {
        ServerSocket listener = new ServerSocket(PORT);
        BufferedReader in;
        while (true) {
            System.out.println("server is waiting for client to connect");
            Socket client = listener.accept();
            in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            String id = in.readLine();
            System.out.println(id);
            ClientHandler clientThread = new ClientHandler(client,clients,id);
            clients.put(id,clientThread);
            pool.execute(clientThread);
        }
    }
}

2) ClientHandler

public ClientHandler(Socket clientSocket, HashMap<String, ClientHandler> clients, String id) throws IOException {
        this.id = id;
        this.client = clientSocket;
        this.clients = clients;
        in = new BufferedReader(new InputStreamReader(client.getInputStream()));
        out = new PrintWriter(client.getOutputStream(), true);
    }

    @Override
    public void run() {
        try {
            while (true) {
                String request = in.readLine();
                System.out.println(request);
                if(request.startsWith("say")){
                    outToAll(request);
                }
            }
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            out.close();
        }
    }
    //this method is used to send message to all the active clients
    public void outToAll(String msg){
            clients.forEach((key,client)->{
                  c.out.println(msg);
            });
        }

3) Клиент

public Client(String id) throws IOException {
        this.id = id;
        this.socket = new Socket(IP_ADDRESS, PORT);
        this.serverConnection = new ServerConnection(socket);
        this.keyboard = new BufferedReader(new InputStreamReader(System.in));
        this.out = new PrintWriter(socket.getOutputStream(), true);
    }

    @Override
    public void run() {
        new Thread(serverConnection).start();
        try {
            out.println(id);
            while (true) {
                String command = keyboard.readLine();
                if (command.equals("quit")) break;
                out.println(command);
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        out.close();
        try {
            socket.close();
            keyboard.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stopSocket() throws IOException {
        socket.close();
    }

4) ServerConnection

//Server connection is connection from client side to the server.which reads message from server and just prints into the console

public ServerConnection(Socket server) throws IOException {
        this.server = server;
        this.in = new BufferedReader(new InputStreamReader(this.server.getInputStream()));
    }
    @Override
    public void run() {
        try{
            while (true){
                String msg = in.readLine();
                if(msg == null) break;
                System.out.println("Server says > "+ msg);
            }
        }catch (Exception e){
            System.out.println(e);
        }finally {

        }
    }

Итак, это мои классы, связанные с сервисом сокетов.

Поскольку я использую javaFX, каждый класс Client Runnable должен запускаться в своем собственном потоке, поэтому для достижения этой цели я создал поток рядом с моим контроллером javaFX с именем HomeController, который вызывается всякий раз, когда клиент входит в систему. Затем HomeController создает клиентскую ветку, как показано ниже

Я надеюсь, что это исправит Это можно сделать, так как мне нужен другой поток, чтобы клиент

не блокировал поток пользовательского интерфейса javafx

    //as I have access to the `id` and already have created a Client object
    // I hope that this the correct way to do so
    this.client = new Client(id);
    new Thread(client).start();

И всякий раз, когда клиент Выйдя из системы, я закрываю клиентский сокет как

    //above created client
    client.stopSocket();

Таким образом, таким образом я создал отдельный поток клиента для каждого клиента, подключенного к серверу.

Сомнение

Я запускаю несколько экземпляров приложения javafx и захожу с разными идентификаторами пользователей.

Итак, в соответствии с реализацией, когда я что-то наберу в клиентской консоли, это должно быть напечатано в каждом и каждая консоль других клиентов тоже. Но это не происходит все время. некоторые клиенты получают сообщение, а некоторые нет, а иногда никто не получает сообщение. Я предполагаю, что некоторые клиенты заблокированы, и я не могу понять.

Поэтому для целей тестирования я создал другой проект с теми же 4 классами и вместо определения класса Client как выполняемого, я создал в нем основной метод , И запустил несколько экземпляров класса Client. Сохраняя покой вещи такими же. Эта реализация прекрасно работает без каких-либо недостатков.

Пожалуйста, помогите мне через это, я уже 4 дня сталкиваюсь с этой проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...