Как сделать несколько сообщений в программировании сокетов?

У меня есть проект, в котором я создаю чат-сервер, где люди (клиенты) подключаются и выбирают партнера для чата. Однако они общаются только тогда, когда оба клиента отправляют сообщение и видят то, что напечатал другой. Я хочу что-то вроде WhatsApp, где мы отправляем много сообщений одно за другим, не дожидаясь отправки другого клиента.

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

//this is the client.java and this is the part of the code where they start chatting
do {
        System.out.print(dis.readUTF());
        System.out.println(dis.readUTF());
        send = in.next();
        dos.writeUTF(send);
        b = dis.readBoolean();
    } while (b);

//this is part of the chatserver.java where the connection is done they start chatting
class handleClient implements Runnable {

    private Socket s1;
    private Socket s2;
    private String name1;
    private String name2;

    public handleClient(Socket s1, Socket s2, String n1, String n2) {
        this.s1 = s1;
        this.s2 = s2;
        this.name1 = n1;
        this.name2 = n2;
    }

    @Override
    public void run() {
        String msg1 = "", msg2 = "";
        boolean b;
        try {
            DataOutputStream dos1 = new DataOutputStream(s1.getOutputStream());
            DataInputStream dis1 = new DataInputStream(s1.getInputStream());

            DataOutputStream dos2 = new DataOutputStream(s2.getOutputStream());
            DataInputStream dis2 = new DataInputStream(s2.getInputStream());

            do {
                dos1.writeUTF(name1 + ": ");
                dos2.writeUTF(name2 + ": ");
                dos2.writeUTF(name1 + ": " + msg1);
                msg1 = dis1.readUTF();
                dos1.writeUTF(name2 + ": " + msg2);
                msg2 = dis2.readUTF();

                b = !msg1.equals(name1 + " is out") && !msg2.equals(name2 + " is out");
                dos1.writeBoolean(b);
                dos2.writeBoolean(b);
            } while (b);

            dos1.close();
            dis1.close();
            dos2.close();
            dis2.close();
            s1.close();
            s2.close();
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
    }
}

Вы должны выполнять чтение и запись в разных потоках или использовать неблокирующий ввод-вывод.

Matt Timmermans 20.05.2019 00:54

спасибо, я попробую ваше предложение.

Elie Tannous 20.05.2019 01:03

создайте сервер веб-сокетов, используя библиотеку, а затем используйте веб-сокет для выполнения своей работы (важно использовать такие протоколы, как веб-сокет, а не писать свои собственные правила)

Mohsen fallahi 20.05.2019 01:04

Я не так хорошо знаком с веб-сокетом, их код - это все, что я знаю в программировании отсосов.

Elie Tannous 20.05.2019 09:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
510
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как сказал @Mohsen fallahi, используйте веб-сокеты (вы получаете неявную неблокирующую функциональность)

Для чистого решения javascript см.: https://javascript.info/вебсокет

Ответ принят как подходящий

readUTF(), ну, читает строку UTF. Он не возвращается, пока не прочитает его. Вот почему вы хотите читать с разных клиентов параллельно, чтобы не имело значения, какой из них отправляет сообщение первым, оно будет прочитано и впоследствии может быть перенаправлено независимо от других. Один из способов сделать это — создать отдельную ветку чтения для каждого клиента.
Вот простой сервер чата (не хотел заниматься подбором клиентов, извините):

public class ChatServer {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(5555);
        List<DataOutputStream> doss = new ArrayList<>();
        while (true) {
            Socket client = server.accept();
            synchronized(doss) {
                doss.add(new DataOutputStream(client.getOutputStream()));
            }
            new Thread(new Runnable() {
                public void run() {
                    try (DataInputStream dis = new DataInputStream(client.getInputStream())) {
                        while (true) {                    // <---------  per-client loop
                            String message=dis.readUTF();
                            synchronized (doss) {
                                for (DataOutputStream dos : doss)
                                    dos.writeUTF(message);
                            }
                        }
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

Он имеет центральное хранилище исходящих потоков (doss) и один поток на каждого клиента для чтения входящих потоков. Затем потоки считывают строку со своего клиента и пересылают ее во все исходящие потоки навсегда (внутренний цикл while(true)).
На стороне клиента циклы практически однострочные, один для чтения сообщения и отправки его на сервер, а другой для получения чего-то с сервера и вывода на экран:

public class ChatClient {
    public static void main(String[] args) throws Exception {
        Scanner s = new Scanner(System.in);
        System.out.print("Enter your nick: ");
        String name = s.nextLine();
        Socket socket = new Socket("localhost", 5555);
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        new Thread(new Runnable() {
            public void run() {
                try {
                    while (true)                              // <------- receiver loop, in thread
                        System.out.println(dis.readUTF());
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }).start();
        dos.writeUTF(name + " has joined the conversation");
        while (true)                                          // <------- sender loop
            dos.writeUTF(name + ": " + s.nextLine());
    }
}

Вещь работает с хардкодом localhost на порту 5555, вообще не обеспечивает обработки ошибок (сервер умирает при уходе клиента). Это должно было быть коротким.

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

Elie Tannous 21.05.2019 15:49

Другие вопросы по теме