socket servidor multiusuario hilos fuente con codigo cliente java sockets server network-programming ioexception

multiusuario - Java: ¿cómo detener un servidor(cerrar un zócalo) sin una excepción?



cliente servidor java socket hilos (1)

Agregué el botón START / STOP que debería iniciar / detener el servidor. Pero el código no funciona como yo quiero: la conexión no está cerrada

Eso es porque estás cerrando ServerSocket , no un socket aceptado.

y el código va a IOException "THIS IS PROBLEM" (en la parte de ServerLogic).

Eso es normal. No hay nada malo aquí.

Además, los clientes aún pueden contactarse con el servidor.

No, no pueden. Los clientes existentes pueden continuar usando sus conexiones existentes . Si quiere cerrarlos, ciérrelos.

¿Cómo cerrar correctamente la conexión sin ninguna excepción?

Solo ciérralos. No puede hacer eso sin incurrir en excepciones en el caso general, y no hay ninguna razón por la que desee hacerlo. Puede ser mejor que los subprocesos de socket aceptados utilicen un tiempo de espera de lectura y cierren y salgan después de obtener un tiempo de espera de lectura, en lugar de anular inmediatamente todas las conexiones existentes. Puede hacer que el tiempo de espera sea lo suficientemente corto, digamos 15 segundos, para que su botón de DETENER sea razonablemente receptivo.

¿Debería antes de cerrar el Socket enviar a todos los clientes algún mensaje con demanda de cierre o simplemente cerrar el Socket en el servidor debería ser suficiente?

Cerrar el zócalo es suficiente. Enviar un mensaje extra no agrega ningún valor. Los clientes obtendrán las indicaciones de fin de ciclo habituales de sus lecturas, o una IOException: connection reset en sus escrituras.

Creé un servidor que permite unirme a muchos clientes.
Sin embargo, tengo un problema.
Agregué el botón START / STOP que debería iniciar / detener el servidor. Pero el código no funciona como yo quiero: la conexión no está cerrada y el código va a IOException "THIS IS PROBLEM" (en la parte de ServerLogic).
Además, los clientes aún pueden contactarse con el servidor.

LÓGICA DEL SERVIDOR

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; } }

SUSCRIPTOR CLIENTE (no se ha eliminado el código necesario)

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 } } }

Botón que maneja 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); } } });

¿Lo que me faltaba?
¿Cómo cerrar correctamente la conexión sin ninguna excepción?
¿Debería antes de cerrar el Socket enviar a todos los clientes algún mensaje con demanda de cierre o simplemente cerrar el Socket en el servidor debería ser suficiente?
Saludos.