Отправка сообщения от сервера к клиенту через сокет

292
23 марта 2017, 19:33

В потоке run() строка: clientSocket.getOutputStream().write(str.getBytes()); не хочет отправлять клиенту сообщение. Сам сервер получает их от клиента, но, как я понимаю, в getOutputStream() ничего не передается. Вопрос почему?

Сервер

public class ServerMain extends  Thread {
    int num;
    public Thread run;
    Socket clientSocket;
    public List<ServerMain> clients2 = new ArrayList<>();
    int port;
    public ServerMain server;
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        int i = 0;
        try {
            serverSocket = new ServerSocket(88);
            System.out.println("Server started on port " + 88);
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (true) {
            try {
                Socket clientSocket = serverSocket.accept();
                new ServerMain(i++, clientSocket);
                System.err.println("Client accepted " + i);
            } catch (IOException x) {
                x.printStackTrace();
            }
        }
    }
    public ServerMain(int num, Socket clientSocket) {
        this.num = num;
        this.clientSocket = clientSocket;
        run();
    }
    public void run() {
        run = new Thread(() -> {
            try {
                InputStream is = clientSocket.getInputStream();
                String str;
                while ((str = reader.readLine()) != null) {
                    System.out.println("Сообщение от клиента: " + str);
                    System.out.flush();
                    //добавляем клиента в коллекцию
                   // clients2.add(new ServerMain(num, clientSocket));         
                    System.out.println(str);
                    clientSocket.getOutputStream().write(str.getBytes());
                }
            } catch (Exception e) {
                System.out.println("Соединение прервалось с клиентом  ");
            }
        }, "run");
        run.start();
    }
}

Клиент (представлен только метод, читающий сокет)

public void send(String bytes) {
    send = new Thread(new Runnable() {
        @Override
        public void run() {
            OutputStream out = null;
            try {
                out = socket.getOutputStream();
            } catch (IOException e) {
                System.out.println("Невозможно получить поток вывода!");
                System.exit(-1);
            }
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
            try {
                writer.write(bytes + "\n");
                writer.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            read();
        }
    });
    send.start();
}
Answer 1

Вот моё решение, возможно вам поможет, сравните с вашим кодом.

В данной программе сервер отправляет всем ранее подключенным клиентам сообщение о подключении нового клиента, все соединения с клиентом хранятся в коллекции.

Запускаете сервер и несколько раз клиент, и при запуске клиента будете видеть соответствующие сообщения у других клиентов и на сервере.

Пояснения:

  • Сервер описан в отдельном классе.
  • Метод .accept(); надо запускать в отдельном потоке, чтобы не останавливать основной поток.
  • Коллекцию соединений храним в статическом поле класса.
  • Каждое соединение с клиентом работает в отдельном потоке.
  • ObjectInputStream и ObjectOutputStream должны создаваться попарно, т.е. Если на стороне сервера вы создали первым ObjectInputStream, то на стороне клиента в первую очередь надо создать ObjectOutputStream.

Надеюсь, я вам помог...

Сервер:

MainServer.java

public class MainServer {
    public static void main(String[] args) {
        System.out.println("server");
        Server server = new Server();
        server.startServer();
    }
}

Server.java

public class Server extends Thread{
    public static List<ClientConnection> connects = new ArrayList<>();
    private final int port = 4444;
    private ServerSocket serverSoket;
    public Server() {
        try {
            serverSoket = new ServerSocket(port);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    public void run() {
        while (true) {
            try {
                ClientConnection clientConnection = new ClientConnection(serverSoket.accept());
                sendMessageAll("added: " + clientConnection.toString());
                Server.connects.add(clientConnection);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
    public void startServer() {
        start();
    }
    public void stopServer() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    public void sendMessageAll(String msg) {
        for(ClientConnection client : connects) {
            client.send(msg);
        }
    }
}

ClientConnection.java

public class ClientConnection extends Thread{
    private Socket soket;
    private ObjectInputStream objectInputStream;
    private ObjectOutputStream objectOutputStream;
    public ClientConnection(Socket soket) throws IOException {
        this.soket = soket;
        objectInputStream = new ObjectInputStream(this.soket.getInputStream());
        objectOutputStream = new ObjectOutputStream(this.soket.getOutputStream());
        System.out.println(this.soket.toString());
        start();
    }
    public void run() {
        try {
            while (true) {
                System.out.print("Client: ");
                String clientMessage = (String) objectInputStream.readObject();
                System.out.println(clientMessage);
            }
        } catch (IOException | ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
    public void send(String message) {
        try {
            System.out.println("Send to: " + this.soket.toString());
            System.out.println(message);
            objectOutputStream.writeObject(message);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Клиент:

MainClient.java

public class MainClient {
    public static void main(String[] args) {
        System.out.println("client");
        Client client = new Client(4444);
        client.Connection();
    }
}

Client.java

public class Client {
    private Socket socket;
    private ObjectInputStream objectInputStream;
    private ObjectOutputStream objectOutputStream;
    private InetAddress addr;
    private int port;
    public Client(int port) {
        try {
            addr = InetAddress.getByName("localhost");
            this.port = port;
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        }
    }
    public void Connection() {
        try {
            socket = new Socket(addr, port);
            objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
            objectInputStream = new ObjectInputStream(socket.getInputStream());
            objectOutputStream.writeObject("Hello, " + this.toString());
            while (true) {
                String serverMessage = (String) objectInputStream.readObject();
                System.out.println(serverMessage);
                objectOutputStream.writeObject("OK : " + socket.toString());
            }
        } catch (IOException | ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}
READ ALSO
Невозможно найти файл конфигурации log4j2

Невозможно найти файл конфигурации log4j2

Почему невозможно найти log4j2 файл конфигурации хотя файл добавленПути файла менял на различные, все равно не находит

374
Создание строки в цикле и оптимизация кода

Создание строки в цикле и оптимизация кода

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

213
Удаление элементов из ArrayList&lt;Object&gt; в Android

Удаление элементов из ArrayList<Object> в Android

В Android-приложении у меня реализован функционал по динамическому добавлению textView в linearLayout, и увеличению высоты этого Layout:

248