Reputation: 173
I'm studying to use ServerSocket
and get an error when trying to close serverSocket
object while method accept()
is working. Next I found solution with setSoTimeout()
method. But I think ignore exception isn't best practice.
So, here's my two classes:
class Server:
public class Server {
public static final int PORT = 8777;
private ServerSocket serverSocket;
private boolean serverRuns;
Server() {
try {
serverSocket = new ServerSocket(PORT);
serverRuns = true;
(new Control(this)).start(); // Takes commands while working
while (serverRuns) {
try {
serverSocket.setSoTimeout(1000);
Socket clientSocket = serverSocket.accept();
}
catch (SocketTimeoutException e) {
// cap
}
}
} catch (IOException e) {
e.printStackTrace();
}
finally {
try {
serverSocket.close();
System.out.println("Server stopped");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stopServer() {
serverRuns = false;
}
public boolean isServerRuns() {
return serverRuns;
}
public static void main(String[] Args) {
Server s = new Server();
}
}
class Control:
public class Control extends Thread {
private Server activeServer;
private Control() {}
Control(Server activeServer) {
this.activeServer = activeServer;
}
@Override
public void run() {
Scanner keyboard = new Scanner(System.in);
while (activeServer.isServerRuns()) {
String key = keyboard.nextLine().toLowerCase();
switch (key) {
case "close":
activeServer.stopServer();
break;
}
}
}
}
Is it correct way to terminate ServerSocket
work(ignore exception and check serverRuns
variable once a second)? Any recommendations are welcome
Upvotes: 1
Views: 4582
Reputation: 19395
Expanding on Xephi's answer:
You need to call the server close from an another Thread
Well, one doesn't need to call the ServerSocket.close()
from the other thread, but it certainly is an advisable approach.
That is exactly what he is already doing. – user207421
No, it is not. What the OP is doing is to reset the serverRuns
flag in the other thread and to periodically check this flag in the main Server
thread with the aid of a socket timeout for the accept()
call; I'd call that rather ugly.
With the recommended approach, the Server
would be like:
Server()
{
try
{
serverSocket = new ServerSocket(PORT);
(new Control(this)).start(); // Takes commands while working
while (true)
{
Socket clientSocket = serverSocket.accept();
…
}
} catch (SocketException e) { System.out.println("Server stopped"); }
catch (IOException e) { e.printStackTrace(); }
}
public void stopServer() throws IOException
{
serverSocket.close();
}
and the Control
loop can be simplified like:
while (true)
{
String key = keyboard.nextLine().toLowerCase();
switch (key)
{
case "close":
activeServer.stopServer();
return;
}
}
Upvotes: 0
Reputation: 431
You need to call the server close from an another Thread, cause serverSocket.accept();
will be blocking
Take a look at: Interrupt accept method and close the server
Upvotes: 1