I do not even know how to correctly describe the problem. In general, I made the Commander class, which uses both the server and the client. Its role is to abstract methods of sending and receiving client / server data. The following problem was created: the client calls several methods of this class, everything works correctly, but when it is called again, the client hangs. I understand that the solution lies in the correct creation of input-output streams, but first I want to at least understand what the matter is before I begin to edit.

import java.io.*; import java.net.Socket; public class Commander { private Socket socket; public Commander(Socket socket) { this.socket = socket; } private void sendObject(Serializable object) throws DisconnectException { try { ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream()); out.writeObject(object); out.flush(); } catch (IOException e) { throw new DisconnectException(); } } private Object receiveObject() throws DisconnectException { Object object = null; try { ObjectInputStream in = new ObjectInputStream(socket.getInputStream()); object = in.readObject(); } catch (IOException e) { throw new DisconnectException(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return object; } public void sendCommand(ServerCommand command) throws DisconnectException { sendObject(command); } public ServerCommand receiveCommand() throws DisconnectException { return (ServerCommand) receiveObject(); } public void sendAccount(Account account) throws DisconnectException { sendObject(account); } public Account receiveAccount() throws DisconnectException { return (Account) receiveObject(); } public void sendAccountID(int id) throws DisconnectException { try { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.writeInt(id); out.flush(); } catch (IOException e) { throw new DisconnectException(); } } public int receiveAccountID() throws DisconnectException { try { DataInputStream in = new DataInputStream(socket.getInputStream()); int id = in.readInt(); return id; } catch (IOException e) { throw new DisconnectException(); } } public void sendAnswer(boolean answer) throws DisconnectException { try { DataOutputStream out = new DataOutputStream(socket.getOutputStream()); out.writeBoolean(answer); out.flush(); } catch (IOException e) { throw new DisconnectException(); } } public boolean receiveAnswer() throws DisconnectException { try { DataInputStream in = new DataInputStream(socket.getInputStream()); boolean answer = in.readBoolean(); return answer; } catch (IOException e) { throw new DisconnectException(); } } public void closeSocket() { try { if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } 

I tried to put all I / O streams into private fields, and in the constructor assign them the necessary links, but it got worse.

Before that, there was also a problem: the program executed one command and the socket was closed, after which an error occurred. It was decided when I read that when opening a stream through try-with-resource (and at that time it was), the socket closes with the stream.


* Edit: Added server side code. This handler is launched via the ExecutorService, with a new connection.

 import java.net.Socket; public class ClientHandler implements Runnable { private Socket socket; private Commander commander; public ClientHandler(Socket socket) { this.socket = socket; this.commander = new Commander(socket); } @Override public void run() { try { ServerCommand command = commander.receiveCommand(); switch (command) { case LOGIN: login(); break; case CREATE_ACCOUNT: createAccount(); break; } } catch (DisconnectException e) { System.out.println(socket.getRemoteSocketAddress().toString() + " was disconnected."); commander.closeSocket(); } } private void login() throws DisconnectException { int id = commander.receiveAccountID(); boolean answer = isAccountExist(id); commander.sendAnswer(answer); if (answer) { commander.sendAccount(Server.getAccounts().get(id)); } } private void createAccount() throws DisconnectException { Account account = commander.receiveAccount(); int id = account.hashCode(); boolean answer = !isAccountExist(id); commander.sendAnswer(answer); if (answer) { Server.getAccounts().put(id, account); } } private boolean isAccountExist(int id) { return Server.getAccounts().keySet().contains(id); } } 
  • What does the server side code look like? - user320999 pm
  • @SpringNewbie added - Vladislav Hukovskii
  • What is the problem? - Roman C
  • @RomanC client calls several methods of this Commander, everything works correctly, but when you call the same commands again, the client hangs. (The client works in one stream) - Vladislav Hukovskii
  • Because synchronization is not done or does not work - Roman C

1 answer 1

In general, the decision was elementary. I tritely forgot to loop the server commands in the method

  @Override public void run() { try { while (true) { ServerCommand command = commander.receiveCommand(); switch (command) { case LOGIN: login(); break; case CREATE_ACCOUNT: createAccount(); break; } } } catch (DisconnectException e) { System.out.println(socket.getRemoteSocketAddress().toString() + " was disconnected."); commander.closeSocket(); } } 
  • It would be logical in the answer to write the corrected method. - talex
  • @talex fixed - Vladislav Hukovskii