I am making a Client-Server Java Swing application where I need to send requests through ObjectOutputStream. I make one request from LoginFrame to check if login/password is correct, server receives data, makes manipulations with it and successfully sends answer back. But when I try to make another call to server, it just doesnt receive it, server kind of stops listening.
Server:
public void runServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server started and listening " + port);
Model.getCountriesAndCities();
System.out.println(Model.getCountries()[0]);
System.out.println(Model.getCountriesMap());
for (int i = 0; i < 50; i++) {
Socket clientSocket = serverSocket.accept();
System.out.println("serversocket accepted");
System.out.println("before oos");
ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
System.out.println("before ois");
ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream());
System.out.println("server is listening");
Map<String, Object> methodData = (Map<String, Object>) ois.readObject();
System.out.println("Server: data received");
String methodName = (String) methodData.get("method");
Object arguments = methodData.get("arguments");
Object result = invokeMethod(methodName, arguments);
oos.writeObject(result);
System.out.println("Server: data sent");
oos.flush();
}
}
Client methods:
public static int checkUser(String login, String password, Client client) {
String query = "SELECT EXISTS(SELECT * FROM users WHERE login = '" + login + "' and password = '" + password + "') as isExist";
String methodName = "CRUDUtils.checkUser";
try {
Map<String, Object> methodData = new HashMap<>();
methodData.put("method", methodName);
methodData.put("arguments", query);
client1.oos.writeObject(methodData);
System.out.println("Client: query sent");
client1.oos.flush();
int check = (Integer) client1.ois.readObject();
System.out.println("chekUser: answer received");
return check;
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
public static String[] getCountries(Client client) {
String query = " ";
String methodName = "Model.getCountries";
ObjectOutputStream oos;
ObjectInputStream ois;
try {
Map<String, Object> methodData = new HashMap<>();
methodData.put("method", methodName);
methodData.put("arguments", query);
client1.oos.writeObject(methodData);
System.out.println("Client: query sent");
client1.oos.flush();
System.out.println("before ois");
String[] check = (String[]) client1.ois.readObject();
System.out.println("getCountries: answer received");
return check;
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
I also have Client class to start socket and swing Frame:
public static void main(String[] args) {
Client klientura = new Client();
try {
klientura.socket = new Socket("localhost", 4444);
klientura.oos = new ObjectOutputStream(klientura.socket.getOutputStream());
klientura.ois = new ObjectInputStream(klientura.socket.getInputStream());
System.out.println("client connected");
Control.client1 = klientura;
LoginFrame loginFrame = new LoginFrame(klientura);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
I tried to replace ObjectOutput and InputOutput, it didn't work. I tried to flush every oos after sending data, it didn't work. I tried to close every oos and ois after using them, it didn't work. I tried everything, thats why this code right now is a mess.
Method checkUser works just fine, but when it comes to run getCountries, the client process just stops on line
String[] check = (String[]) client1.ois.readObject();
The last message in client console is "before ois", it means that client1.oos.writeObject(methodData)
is completed, but server doesnt respond to that.
The last message in server console is "Server: data sent", it means that server sent data to checkUser method and stopped listening.
As per the documentation, accept() listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made.
Your current implementation looks like it is re-using the same connection for each request. Therefore, the server is blocking at the accept() method because the client is never making a new connection.
I would suggest leveraging threading on the server. On the main thread listen for new connections. Once a connection is made, the accept() method will return a Socket instance. At this point create a new thread and pass in the socket reference. Have all of the request/response processing logic in the new thread.
This will allow you to read and write to sockets, while also listening for new connections to the server.
public void runServer() {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Server started and listening " + port);
while(true){
try {
Socket socket = serverSocket.accept();
Task task = new Task(socket);
(new Thread(task)).start();
} catch(IOException e){
// Handle
}
}
}
public class Task implements Runnable {
private final Socket socket;
public Task(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
// Loop that reads from and writes to socket
}
}