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

public class Server extends Thread {
    ServerSocket serverSocket = null;
    Socket socket = null;
    private int unique_id;
    ArrayList<Clients> cl;


    public Server(int port) {
        try { 
            serverSocket = new ServerSocket(port);
            cl = new ArrayList<>();
            this.start();
        } catch (Exception e){
            System.out.println("Error 5");
            e.printStackTrace();
        }
    }
    @Override
    public void run(){
        System.out.println("Server Start");
            while (true){
                try {
                    socket = serverSocket.accept();
                    Clients t = new Clients(socket); // add it to thread
                    cl.add(t);
                    t.start();
                    System.out.println("Connected " + String.valueOf(cl.size())); // printed ok 
                }catch (Exception e){
                    System.out.println("Error 4");
                    e.printStackTrace();
                }
            }
    }
    public synchronized void SendToAll(String s){ // this function used by client when one of client socket send a message then server send it to all
        System.out.println("Sended is excuted"); // excuted normal each time i send a message from client but not send to all  
        for (int i = 0; i < cl.size(); i++){
            cl.get(i).WriteToSocket(s);
        }
    }

    public static void main(String args[]){
        int port = 5002;
        Server server = new Server(port); // start server
        //server.run(); // start connections wait for it
    }

    class Clients extends Thread { // class extends thread
        public Socket socket = null;
        DataInputStream input = null; // read input
        DataOutputStream output = null; // read output
        public int myid = 0; // unique id for each client

        public Clients(Socket soc) {
            socket = soc;
            try {
                input = new DataInputStream(socket.getInputStream());
                output = new DataOutputStream(socket.getOutputStream());
                myid = ++unique_id;
                System.out.println("Client Start Thread"); // printed ok !
            } catch (IOException e){
                System.out.println("Error 1");
                e.printStackTrace();
            }
        }
        public void WriteToSocket(String s) { // used to write a message to this socket
            try {
                output.write(s.getBytes());
            }catch (IOException e){
                System.out.println("Error 2");
                e.printStackTrace();
            }
        }
        @Override
        public void run() { // run thread function wait for messages from clients 
            while (true){
                try {
                    String s = input.readLine();
                    if (s.contains("quite")) {
                        socket.close();
                        input.close();
                        output.close();
                        cl.remove(this);
                        this.stop();
                    }
                    if (!s.isEmpty()) {
                        SendToAll(s);// when message come and not empty it use server function to send them to all clients 
                    }
                }catch (IOException e){
                    System.out.println("Error 3");
                    e.printStackTrace();
                }
            }
        } 
    }
}

Все работает нормально, когда клиенты подключаются к серверу, принимают соединение и запускается клиентский поток
но проблема, когда я отправил сообщение от клиента, которое не было получено сервером, я тоже пробую свое клиентское приложение на java с сервером Qt C ++, и оно работает?так что я сделал не так, что сервер не может получить сообщение?это мой первый раз в сетевом программировании с использованием java
Изменить
Я решаю NullPointerException проблема заключалась в том, что когда клиент вышел из системы, я не удалил его сокет из ArrayList, что было решено путем создания сообщения client before close send, которое содержит именно так, когда я вижу я удаляю его сокет из списка массивов
Другой Quetiosn
Здесь я не знаю, как это сообщение отправило
System.out.println (), которая находится в функция SendToAll выводится на экран каждый раз, когда клиент отправляет сообщение, но почему это сообщение не отправляется снова всем клиентам?
на самом деле основная проблема заключается в том, что сервер не может отправить сообщение всем клиентам в списке массивов после того, как сообщение пришло от одного клиента, проблема не решена, stell found
Класс клиентского кода

public class ClientSocket extends Thread {
    public Socket socket = null;
    public DataInputStream input = null;
    public DataOutputStream output = null;
    MainChat chat = null;

    public ClientSocket(String ip, int port,MainChat ch) {
        try {
            socket = new Socket(ip,port);
            input = new DataInputStream(socket.getInputStream());
            output = new DataOutputStream(socket.getOutputStream());
            chat = ch;
            this.start();
        }catch (IOException e){

        }
    }
    @Override
    public void run() {
        while (true){
            try {
                String s = input.readLine();
                if (!s.isEmpty()){
                   chat.WriteToScreen(s.trim());
                }
            }catch (IOException e){

            }
        }
    }
    public void WriteToSocket(String s) throws IOException{
        output.write(s.getBytes());
    }

}

Редактировать
когда я использую этот код в основном, функция SendToAll отправляет сообщение всем клиентам !! почему, когда я использую его из класса клиентов с помощью Thread, он не отправляется всем?

public static void main(String args[]){
    int port = 5002;
    Server server = new Server(port); // start server
    //server.run(); // start connections wait for it
    while (true) {
        String s = in.next();
        server.SendToAll(s + "\n"); // message sended to all client !!
    }
}
1
user7179690 27 Ноя 2016 в 01:55

2 ответа

Лучший ответ

Проблема в том, что readLine читает, пока не найдет признак конца строки в конце файла. Вот почему он работает с другим сервером в QT C ++, но не с сервером Java. См. Здесь: https://docs.oracle. com / javase / 7 / docs / api / java / io / DataInput.html # readLine () https://docs.oracle. com / javase / 7 / docs / api / java / io / DataInputStream.html # readLine ()

Обратите внимание, что readLine в DataInputStream устарел. Для чтения строки следует использовать BufferedReader. (с readLine), как указано в Ссылка DataInputStream.

Итак, добавьте '\ n' в конец отправленной строки, и все заработает.

1
rodolk 28 Ноя 2016 в 03:36

Я решаю проблему. Прошу прощения за то, что это была моя вина. Я забыл добавить \ n в функцию sendToAll, поэтому проблема возникает из-за этого, поэтому клиенты не могут прочитать строку, потому что я использовать readLine в DataInputStream
в любом случае я пробую другой метод чтения байтов вместо readLine, я думаю, что это лучше, особенно когда вы получаете символ UTF-8 и после этого меняете с байтов на String

0
user7179690 27 Ноя 2016 в 21:01