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 ...
while ((len = from_server.read(rec_frmserver)) != -1)will work untilreadreturns-1,readdoes not return-1as long as the stream can be read (the connection is not closed), and if there is no data in the stream now , thereadwill wait until they appear. TCP - streaming protocol, stream analysis on commands is assigned to the application layer. You can wrap the read into theBufferedReader, send lines ending in\n, and read throughreadLine. You can useDataInputStreamandDataOutputStream, or inline serialization. - zRrr