I'm writing an email application in javafx, using MVC architecture. The starting method of the server is this.
@Override
public void run() {
try {
serverSocket = new ServerSocket(PORT);
controller.logEvent(Protocol.SERVER_STARTED, true, null, null);
loadAccounts();
while (isRunning.get()) {
try {
Socket socket = serverSocket.accept();
if (isRunning.get()) {
connectedClients.add(socket);
Thread thread = new Thread(() -> {
handleClient(socket);
connectedClients.remove(socket);
});
thread.start();
} else {
socket.close();
}
} catch (SocketException e) {
if (!isRunning.get()) {
break;
} else {
throw e;
}
}
}
} catch (IOException e) {
controller.logEvent(Protocol.SERVER_STARTED, false, null, null);
e.printStackTrace();
}
}
While instead the one to stop the server is this:
public void stopServer() {
isRunning.set(false);
try {
if (serverSocket != null) {
serverSocket.setReuseAddress(true);
serverSocket.close();
controller.logEvent(Protocol.SERVER_STOPPED, true, null, null);
for (Socket socket : connectedClients) {
socket.close();
}
connectedClients.clear();
}
} catch (IOException e) {
controller.logEvent(Protocol.SERVER_STOPPED, false, null, null);
e.printStackTrace();
}
}
My problem lies in restarting the server. When I try to restart it, it gives me these errors:
java.net.BindException: Address already in use (Bind failed)
at java.base/java.net.PlainSocketImpl.socketBind(Native Method)
at java.base/java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:452)
at java.base/java.net.ServerSocket.bind(ServerSocket.java:395)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:257)
at java.base/java.net.ServerSocket.<init>(ServerSocket.java:149)
at MailServer.run(MailServer.java:71)
at java.base/java.lang.Thread.run(Thread.java:829)
My method for restarting the server was this:
public void startServer() {
try {
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.setReuseAddress(true);
serverSocket.close();
}
isRunning.set(true);
serverSocket = new ServerSocket(PORT);
Thread thread = new Thread(this);
thread.start();
controller.logEvent(Protocol.SERVER_STARTED, true, null, null);
} catch (IOException e) {
controller.logEvent(Protocol.SERVER_STARTED, false, null, null);
}
}
Do you have any tips to solve my problem? I figured out that the problem is that the port is not freed when the server is stopped, but I have no idea how I can fix it.
run()creates a newServerSocketon the same port as the one created by thestartServer()method. Given the presence of astartServer()method, you should remove the creation of theServerSocketin therun()method. Additionally, you seem to be using#setReuseAddress(boolean)incorrectly. The effects of that method are undefined for an already-bound socket. Create an unbound socket, call that method, then callbind.