Good time to all! Help me please. The goal is to implement a client-server messaging application.

Customer:

class ClientThread extends Thread { private Socket socket; //размер буфера сокета private int sz_buf_sock; //Буфер для получения данных от сервера private BufferedInputStream from_server; //Буфер отправки данных серверу private BufferedOutputStream to_server; //Поток ввода с консоли private Scanner scann; // private ByteArrayOutputStream baos_fs; //Буфер для приёма байтов с сервера byte[] rec_frmserver; //конструктор public ClientThread(InetAddress addr) { try { socket = new Socket(addr, MultiServer.PORT); } catch (IOException e) { System.err.println("Server is not running!"); } try { //Инициализация потока получения данных от сервера from_server = new BufferedInputStream(socket.getInputStream()); //Инициализация потока для отправки данных серверу to_server = new BufferedOutputStream(socket.getOutputStream()); //Поток ввода scann = new Scanner(System.in); sz_buf_sock = socket.getReceiveBufferSize(); rec_frmserver = new byte[sz_buf_sock]; start(); } catch (IOException e) { // Сокет должен быть закрыт при любой // ошибке, кроме ошибки конструктора сокета try { socket.close(); } catch (IOException e2) { System.err.println("Socket not closed"); } } // В противном случае сокет будет закрыт // в методе run() }//конец конструктора @Override public void run() { try { while (true) { //здесь читаем в бесконечном цикле сообщения, пока не введем "END" String input_command = scann.next(); byte[] inpc_b = input_command.getBytes(); System.out.println(input_command); to_server.write(inpc_b); to_server.flush(); //если на стороне клиента ввели END, то прекращаем сессию if (input_command.equals("END")) break; byte[] data; //Читаем данные полученные от сервера int len; //Здесь rec_frmserver - буфер для считывания данных с сервера(его размер - размер буфера сокета) - 8кб while ((len = from_server.read(rec_frmserver)) != -1) { baos_fs = new ByteArrayOutputStream(); baos_fs.write(rec_frmserver, 0, len); baos_fs.flush(); data = baos_fs.toByteArray(); baos_fs.close(); String str = new String(data); } //что-то делаем с прочитанными данными }//конец цикла }//конец блока try и дальше идёт обработка исключений и закрытие потоков catch (IOException e) { System.err.println("Server is unreachable..." + '\n'); e.printStackTrace(); } finally { try { to_server.close(); from_server.close(); socket.close(); System.out.println("End session..."); } catch (IOException e) { System.err.println("Socket not closed..."); e.printStackTrace(); } } 

Server:

 class ServeOne extends Thread { // private Socket socket; // private int sz_buf_sock; //Буфер для получения данных от клиента private BufferedInputStream from_client; //Буфер для отправки данных клиенту private BufferedOutputStream to_client; //Буфер для полученной команды byte[] rec_frclient; public ServeOne(Socket s) throws IOException { socket = s; //Инициализация потока получения данных от клиента from_client = new BufferedInputStream(socket.getInputStream()); //Инициализация потока птправки данных клиенту to_client = new BufferedOutputStream(socket.getOutputStream()); sz_buf_sock = socket.getReceiveBufferSize(); rec_frclient = new byte[sz_buf_sock]; //Запускаем поток start(); } @Override public void run() { //Обрабатываем полученные данные try { while (true) { byte[] data; //Читаем данные полученные от клиента //Здесь rec_frclient - буфер для считывания данных полученных от клиента(его размерность - размер буфера сокета 8 кб) int len = from_client.read(rec_frclient); data = new byte[len]; for (int i = 0; i < len; i++) data[i] = rec_frclient[i]; String rec_command = new String(data); if (rec_command.equals("END")) break; //отправили данные клиенту to_client.write(data, 0, data.length); to_client.flush(); } }//далее обрабатывае исключения и закрываем потоки catch (IOException e) { System.err.println("IO Exception"); e.printStackTrace(); } finally { try { to_client.close(); from_client.close(); System.out.println("Client disconnect..."); socket.close(); } catch (IOException e) { System.err.println("Socket not closed..."); e.printStackTrace(); } } 

I run this whole thing like this:

 public class MultiServer { static final int PORT = 8080; public static void main(String[] args) throws IOException { ServerSocket s = new ServerSocket(PORT); System.out.println("Server Started..."); try { while (true) { //Подключаем клиента Socket socket = s.accept(); try { //Новое соединение ServeOne serveOne = new ServeOne(socket); } catch (IOException e) { // Если завершится неудачей, закрывам сокет. // в противном случае, нить закроет его socket.close(); } } } finally { s.close(); } } } 

And:

 public class RunTClient { public static void main(String[] args) throws IOException, InterruptedException { //Получили адрес локальной машины InetAddress addr = InetAddress.getByName(null); new ClientThread(addr); } } 

The problem is as follows: When a client enters a string and sends it to the Server, the server "hangs" tightly into int len = from_client.read(rec_frclient); or in while ((len = from_server.read(rec_frmserver)) != -1) and if you kill the thread manually, an exception is thrown

 Server is unreachable... java.net.SocketException: Connection reset at java.net.SocketInputStream.read(Unknown Source) at java.net.SocketInputStream.read(Unknown Source) at java.io.BufferedInputStream.read1(Unknown Source) at java.io.BufferedInputStream.read(Unknown Source) at java.io.FilterInputStream.read(Unknown Source) at ClientThread.run(ClientThread.java:149) 

Moreover, if you initially send the command "END", the client will end the session and everything will be fine. Help please deal with this exception. Everything has already broken his head ...

  • one
    so this is normal behavior. while ((len = from_server.read(rec_frmserver)) != -1) will work until read returns -1 , read does not return -1 as long as the stream can be read (the connection is not closed), and if there is no data in the stream now , the read will wait until they appear. TCP - streaming protocol, stream analysis on commands is assigned to the application layer. You can wrap the read into the BufferedReader , send lines ending in \n , and read through readLine . You can use DataInputStream and DataOutputStream , or inline serialization. - zRrr
  • @zRrr thanks for the reply. I will try to follow your instructions. - rekrut

0