Заставить сервер ждать ввода от двух разных контроллеров - PullRequest
0 голосов
/ 04 декабря 2018

Я создал клиент-серверное приложение, в котором сервер должен отправить клиенту список электронных писем, который после загрузки в ListView дает возможность через панель меню удалить их.В клиенте все эти операции выполняются в модели данных (я следовал шаблону MVC).Это сервер:

class ThreadedEchoHandler implements Runnable {

    private Socket incoming;

    private String nomeAccount = "";

    public void run() {
        try {
            incoming = s.accept();
        } catch (IOException ex) {
            System.out.println("Unable to accept requests");
        }
        contenutoTextArea.append("Connected from: " + incoming.getLocalAddress() + "\n");
        textarea.setText(contenutoTextArea.toString());
        try {
            //PHASE 1: The server receives the email
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
                nomeAccount = in.readLine();
            } catch (IOException ex) {
                System.out.println("Not works");
            }

            //PHASE 2: I'm getting all the emails from the files
            File dir = new File("src/server/" + nomeAccount);
            String[] tmp = new String[100];
            int i = 0;
            for (File file : dir.listFiles()) {
                if (file.isFile() && !(file.getName().equals(".DS_Store"))) {
                    try (BufferedReader br = new BufferedReader(new FileReader(file))) {
                        String line;
                        while ((line = br.readLine()) != null) {
                            tmp[i++] = line;
                        }
                    } catch (IOException ex) {
                        System.out.println("Cannot read from file");
                    }
                }
            }

            //PHASE 3: The server sends the ArrayList to the client
            PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
            for (int j = 0; j < i; j++) {
                out.println(tmp[j]); // send the strings to the client
            }
        } catch (IOException ex) {
            System.out.println("Cannot send the strings to the client");
        }

        //PHASE 4: Here I loop and wait for the client choise
        BufferedReader in;
        String op;
        try {
            in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
            while ((op = in.readLine()) != null) {                   
                if (op.equals("Elimina")) {
                    String tmp = in.readLine();
                    File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
                    file.delete();
                } else if (op.equals("Invia")) {
                    //...
                } else {
                    //...
                }
            }
        } catch (IOException ex) {
            System.out.println("Non so");

        } finally {
            try {
                incoming.close();
            } catch (IOException ex) {
                System.out.println("Cannot closing the socket");
            }
        }
    }
}

Это методы клиента:

public void loadData() throws IOException, ClassNotFoundException, ParseException {

    try {
        s = new Socket("127.0.0.1", 5000);
        ArrayList<Email> email = new ArrayList<Email>();
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
        Date data;

        /* PHASE 1: The client sends a string to the server */
        //try {
            PrintWriter out = new PrintWriter(s.getOutputStream(), true);
            out.println(account); // send the account name to server

            /* PHASE 2: The client receives the ArrayList with the emails */
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            String line;
            String message[] = new String[5];
            for (int j=0; (line = in.readLine()) != null;) {
                message[j++] = line;
                if (j==5) {
                    data = format.parse(message[3]);
                    email.add(new Email((Integer.parseInt(message[0])), message[1], account, message[2], message[4], data));
                    j=0;
                }
            }

            //Casting the arrayList
            emailList = FXCollections.observableArrayList(email);

            //Sorting the emails
            Collections.sort(emailList, (Email o1, Email o2) -> {
                if (o1.getData() == null || o2.getData() == null) {
                    return 0;
                }
                return o1.getData().compareTo(o2.getData());
            });

        /*} finally {
            s.close();*/
        //}
    } catch (SocketException se) {
        emailList.setAll(null, null);
    }
}

public void deleteMail(Email da_elim) throws IOException {
    int id_del = da_elim.getID();
    emailList.remove(da_elim);
    PrintWriter out = new PrintWriter(s.getOutputStream(), true);
    out.println("Elimina");
    out.println(id_del);
}

ФАЗЫ 1, 2, 3 Сервера предназначены для загрузки электронных писем, иработать с методом loadData ().Без ФАЗЫ 4 программа работает.Теперь, если я пишу этот цикл, графический интерфейс клиента не загружается, и я не могу нажать на кнопку УДАЛИТЬ (что должно сделать ввод, чтобы включить что-то (в этом исключение файла) в этот цикл. Почему клиентне загружается, даже если это два разных потока? И почему без этого цикла это работает?

РЕДАКТИРОВАТЬ: с реализованным классом Listener, но все еще не работает

//PHASE 4: Here I loop and wait for the client choise      
        BufferedReader in;
        String op;
        try {
            in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
            /*while ((op = in.readLine()) != null) {
                System.out.println("OP: " + op);
                if (op.equals("Elimina")) {
                    String tmp = in.readLine();
                    contenutoTextArea.append("Ho eliminato la mail ").append(tmp).append(" \n");
                    textarea.setText(contenutoTextArea.toString());
                    File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
                    file.delete();
                }
            }*/
            Listener lis = new Listener(in, new LinkedBlockingQueue<String>());
            lis.run();
            System.out.println("bbbbb");
        } catch (IOException ex) {
            System.out.println("Unable to read messages");
        } finally {
            try {
                incoming.close();
            } catch (IOException ex) {
                System.out.println("Cannot close the socket");
            }
        }

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

В настоящее время я не могу комментировать, поэтому не могу просить разъяснений, но думаю, что правильно интерпретирую, что не так.Msgstr "Программа зависает, когда входит в цикл, который ожидает ввода от двух контроллеров".Предполагая, что я правильно понял эту часть, наиболее вероятным виновником будет то, что буферизованный читатель зависает бесконечно, потому что не получает ввод.Когда я впервые столкнулся с этой проблемой, я бросил ее в свой собственный класс "приемника" и использовал очередь для передачи по всему, что он получил, в цикл в моем основном классе.мой код выглядел примерно так:

import java.io.BufferedReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;

public class Listener implements Runnable
{
    private BufferedReader br;
    private BlockingQueue<String> q;
    private boolean shouldClose = false;

    public Listener(BufferedReader br, BlockingQueue<String> q)
    {
        this.q = q;
        this.br = br;
    }

    public void run()
    {
        loop();
        System.out.println("listener has stopped");
    }

    public void loop()
    {
        String line = "";

        try
        {
            while((line = br.readLine()) != null && !shouldClose)
            {
                q.put(line);
            }
        }
        catch (IOException | InterruptedException e)
        {
            e.printStackTrace();
        }
    }

    public void shutdown()
    {
        shouldClose = true;
    }
}

извинения, если я что-то неправильно понял или что-то упустил в вашем коде.

0 голосов
/ 06 декабря 2018

Я думаю, вы должны запустить jvisualvm (это инструмент, установленный с jdk в / bin / location вашего jdk) и искать тот жизненный цикл Thread, который вы создаете на сервере.Также проверьте, что ваш поток не проходит через код и просто заканчивает свою жизнь, пропуская ожидание клиента.

Связан ли этот поток с клиентом?Потому что вы не можете запустить клиентское приложение.Они разделены?Еще одна мысль, которая пришла мне в голову, - это использовать

Platform.runLater(()->{
});

, если ваш клиентский графический интерфейс находится в JavaFX.Используйте его, если вы создаете GUI, меняете значения в полях и все, что вы делаете в GUI.Может быть, ваш сервер ждет ответа пользователя и после этого построен графический интерфейс?По этой причине вы не можете нажать кнопку УДАЛИТЬ.

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