检查客户端套接字是否在服务器上关闭

Check if client socket is closed on the server

如何在服务器端检查客户端是否关闭了套接字?

我有这个服务器,它等待连接然后 return 10 条消息到客户端:

public class SocketServidor {
    static ServerSocket serverSocket;

    public static void main(String[] args) throws Exception {
        serverSocket = new ServerSocket(5963);
        while(true) {
            final Socket socket = serverSocket.accept();
            new Thread(() -> {
                try {
                    PrintWriter out = new PrintWriter(socket.getOutputStream());
                    for (int i = 0; i < 10; i++) {
                        int valor = (int) (Math.random() * 5) + 1;
                        out.println("Você acabou de ganhar R$ "+new DecimalFormat("###,##0.00").format(valor)+"!");
                        out.flush();
                        Thread.sleep(valor*1000);
                    }
                    socket.close();
                } catch (Exception ex) {
                    Logger.getLogger(SocketServidor.class.getName()).log(Level.SEVERE, null, ex);
                }
            }).start();
        }
    }
}

客户端只读取值,但在第五次读取时停止:

public class SocketCliente {

    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("localhost", 5963);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String leitura;
        int lidas = 0;
        while((leitura = in.readLine()) != null) {
            lidas++;
            System.out.println(leitura);
            if(lidas == 5){
                socket.close();
            }
        }
    }

}

问题是,即使在第五次读取之后,当客户端关闭套接字时,服务器仍继续向客户端发送消息。如何在客户端关闭套接字时关闭服务器端的套接字?

异常被 PrintWriter.flush()
抑制 您看不到异常,因为 PrintWriter.flush() 抑制了异常。要检查 PrintWriter.println() 之后的错误状态,您可以使用 PrintWriter.checkError() 而不是 flush()。或者,您可以使用 OutputStreamWriter 而不是 PrintWriter,这样异常就不会被抑制。

  1. 有checkError

    serverSocket = new ServerSocket(5963);
    while(true) {
        final Socket socket = serverSocket.accept();
        new Thread(() -> {
            try {
                PrintWriter out = new PrintWriter(socket.getOutputStream());
                for (int i = 0; i < 10; i++) {
                    int valor = (int) (Math.random() * 5) + 1;
                    out.println("Você acabou de ganhar R$ "+new DecimalFormat("###,##0.00").format(valor)+"!");
                    //out.flush();
                    if(out.checkError()){
                        System.out.println("Error. Break");
                        break;
                    }
                    Thread.sleep(valor*1000);
                }
                socket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }).start();
    }
    
  2. 带OutputStreamWriter

    serverSocket = new ServerSocket(5963);
    while(true) {
        final Socket socket = serverSocket.accept();
        new Thread(() -> {
            try {
                Writer out = new OutputStreamWriter(socket.getOutputStream());
                for (int i = 0; i < 10; i++) {
                    int valor = (int) (Math.random() * 5) + 1;
                    out.write("Você acabou de ganhar R$ "+new DecimalFormat("###,##0.00").format(valor)+"!");
                    out.write("\r\n");
                    out.flush();
                    Thread.sleep(valor*1000);
                }
                socket.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }).start();
    }