I've made a server which allows to join many clients.
However I have a problem.
I added START/STOP button which should start/stop server. But the code does not work like I want: connection isn't closed and code goes to the IOException "THIS IS PROBLEM" (in ServerLogic part).
Additionally clients still can contact with server.
SERVER LOGIC
public class ServerLogic
{
private static ServerSocket m_sSocket;
private static Set<ServerSubscriber> m_subscriberList = new HashSet<ServerSubscriber>();
private static boolean m_isServerRun = false;
private static class ServerLogicHolder
{
static final ServerLogic INSTANCE = new ServerLogic();
}
private ServerLogic()
{}
public static ServerLogic getServerLogic()
{
return ServerLogicHolder.INSTANCE;
}
/**
* It starts listening of incoming connections from the clients.
*
* @param port
*/
public void startListening(int port)
{
try
{
if (!m_isServerRun)
{
m_sSocket = new ServerSocket(port);
K6s.getUiServerConsole().addLine(Config.LOG_START);
m_isServerRun = true;
}
else
{
System.out.println(Config.LOG_ERROR1);
}
}
catch (IOException e)
{
System.out.println(Config.LOG_ERROR1);
}
try
{
while (isServerRun())
{
new Thread(new ServerSubscriber(m_sSocket.accept(), K6s.getUiServerConsole())).start();
}
}
catch (IOException e1)
{
/*
java.net.SocketException: socket closed
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at java.net.DualStackPlainSocketImpl.socketAccept(Unknown Source)
at java.net.AbstractPlainSocketImpl.accept(Unknown Source)
at java.net.PlainSocketImpl.accept(Unknown Source)
at java.net.ServerSocket.implAccept(Unknown Source)
at java.net.ServerSocket.accept(Unknown Source)
at org.czarny.k6s.comm.ServerLogic.startListening(ServerLogic.java:69)
at org.czarny.k6s.gui.K6s$2$1.run(K6s.java:138)
at java.lang.Thread.run(Unknown Source)
*/
}
}
/**
* Just close server's socket.
*/
public void stopListening()
{
if (m_isServerRun)
{
try
{
m_isServerRun = false;
m_sSocket.close();
m_sSocket = null;
}
catch (IOException e)
{
m_isServerRun = true;
System.out.println(Config.LOG_ERROR4);
}
}
}
public HashSet<ServerSubscriber> getSubscriberList()
{
return (HashSet<ServerSubscriber>) m_subscriberList;
}
public boolean isServerRun()
{
return m_isServerRun;
}
}
CLIENT SUBSCRIBER (not neccessary code has been removed)
public class ServerSubscriber implements Runnable
{
private Socket m_socket;
private LogComponent m_serverConsole;
private PrintWriter m_outComm;
private String m_subscriberIP;
private String m_subscriberName;
private String m_subsctiberLogInfo;
ServerSubscriber(Socket socket, LogComponent serverConsole)
{
m_socket = socket;
m_serverConsole = serverConsole;
try
{
m_outComm = new PrintWriter(socket.getOutputStream(), true);
}
catch (IOException e)
{
e.printStackTrace();
}
sendMessage(Config.MSG_HANDSHAKE);
}
/**
* This method runs messages from this subscriber.
*/
public void run()
{
String line;
BufferedReader inComm = null;
try
{
inComm = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
}
catch (IOException e)
{
m_serverConsole.addLine(Config.LOG_ERROR3);
}
while (ServerLogic.getServerLogic().isServerRun())
{
try
{
//do something here
}
}
}
Button which handles START/STOP
uiStart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
if (!ServerLogic.getServerLogic().isServerRun())
{
uiStart.setText(Config.GUI_BTN_STOP);
new Thread(new Runnable()
{
public void run()
{
try
{
ServerLogic.getServerLogic().startListening(Integer.parseInt(uiServerPort.getText()));
}
catch (Exception e)
{
e.printStackTrace();
}
}
}).start();
}
else
{
ServerLogic.getServerLogic().stopListening();
m_uiServerConsole.addLine(Config.LOG_STOP);
uiStart.setText(Config.GUI_BTN_START);
}
}
});
What I missed?
How to properly close connection without any exceptions?
Should I just before closing the Socket send to all clients some message with demand of closeure or just closing the Socket on the server should be enough?
Regards.
I added START/STOP button which should start/stop server. But the code does not work like I want: connection isn't closed
That's because you're closing the ServerSocket
, not an accepted socket.
and code goes to the IOException "THIS IS PROBLEM" (in ServerLogic part).
That's normal. Nothing wrong here.
Additionally clients still can contact with server.
Existing clients can continue to use their existing connections. If you want to close those, see next. No new connections can be created.
How to properly close connection without any exceptions?
Shut them down for input. That will cause the reads to incur an end of stream, which should already cause the threads concerned to close the socket and exit.
Should I just before closing the Socket send to all clients some message with demand of closeure or just closing the Socket on the server should be enough?
Closing the socket is sufficient. Sending an extra message doesn't add any value. The clients will get the usual end-of-stream indications from their reads, or an IOException: connection reset
on their writes.
来源:https://stackoverflow.com/questions/39276549/java-how-to-stop-a-server-close-a-socket-without-an-exception