御坂主机 发表于 2024-6-30 11:58:48

javax.net.ssl.SSLException:closing inbound before receiving peer‘s close_notify

本帖最后由 御坂主机 于 2024-7-3 18:23 编辑

1. 概述

在使用Java进行网络编程时,可能会遇到各种SSL/TLS相关的问题。其中一个常见的错误是“javax.net.ssl.SSLException: closing inbound before receiving peer‘s close_notify”。这个错误通常出现在SSL连接的关闭过程中,表示在接收到对等方的`close_notify`消息之前关闭了输入流。本文将详细介绍该错误的原因及解决方案。

1.1 错误背景

SSL/TLS协议在关闭连接时,要求通信双方发送并接收`close_notify`消息,以确保连接的有序关闭。如果在接收对等方的`close_notify`消息之前关闭了输入流,就会引发`javax.net.ssl.SSLException: closing inbound before receiving peer‘s close_notify`错误。这种情况可能出现在客户端或服务器端。

1.2 解决方案概述

为了解决这一问题,我们需要确保在关闭SSL连接时正确处理`close_notify`消息。具体的解决方案包括正确关闭连接、捕获并处理异常等。本文将详细介绍这些解决方案,并提供相应的代码示例。

2. 正确关闭SSL连接

2.1 客户端正确关闭连接

在客户端程序中,正确关闭SSL连接可以避免该错误。以下是一个示例,展示了如何在客户端中正确关闭SSL连接:

    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.SSLSocketFactory;
    import java.io.OutputStream;
    import java.io.InputStream;

    public class SSLClient {
      public static void main(String[] args) {
            try {
                SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
                SSLSocket socket = (SSLSocket) factory.createSocket("localhost", 8443);

                OutputStream outputStream = socket.getOutputStream();
                InputStream inputStream = socket.getInputStream();

                // 发送数据
                outputStream.write("Hello Server".getBytes());
                outputStream.flush();

                // 读取服务器响应
                byte[] buffer = new byte;
                int bytesRead = inputStream.read(buffer);
                System.out.println(new String(buffer, 0, bytesRead));

                // 关闭输出流,触发发送close_notify消息
                socket.getOutputStream().close();

                // 关闭输入流,确保接收服务器的close_notify消息
                socket.getInputStream().close();

                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
      }
    }

在上述代码中,`socket.getOutputStream().close()`用于关闭输出流,触发发送`close_notify`消息;`socket.getInputStream().close()`确保接收服务器的`close_notify`消息,然后关闭输入流。

2.2 服务器正确关闭连接

在服务器程序中,同样需要正确关闭SSL连接。以下是一个示例,展示了如何在服务器中正确关闭SSL连接:

    import javax.net.ssl.SSLServerSocket;
    import javax.net.ssl.SSLServerSocketFactory;
    import javax.net.ssl.SSLSocket;
    import java.io.OutputStream;
    import java.io.InputStream;

    public class SSLServer {
      public static void main(String[] args) {
            try {
                SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
                SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(8443);

                while (true) {
                  SSLSocket socket = (SSLSocket) serverSocket.accept();

                  OutputStream outputStream = socket.getOutputStream();
                  InputStream inputStream = socket.getInputStream();

                  // 读取客户端数据
                  byte[] buffer = new byte;
                  int bytesRead = inputStream.read(buffer);
                  System.out.println(new String(buffer, 0, bytesRead));

                  // 发送响应
                  outputStream.write("Hello Client".getBytes());
                  outputStream.flush();

                  // 关闭输出流,触发发送close_notify消息
                  socket.getOutputStream().close();

                  // 关闭输入流,确保接收客户端的close_notify消息
                  socket.getInputStream().close();

                  socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
      }
    }

在上述代码中,同样通过关闭输出流和输入流,确保在关闭连接时正确处理`close_notify`消息。

3. 捕获并处理异常

在某些情况下,即使按照上述方法关闭连接,仍可能遇到`javax.net.ssl.SSLException: closing inbound before receiving peer‘s close_notify`错误。此时,可以通过捕获并处理该异常来确保程序的稳定性。

    try {
      // 关闭输出流,触发发送close_notify消息
      socket.getOutputStream().close();

      // 关闭输入流,确保接收对等方的close_notify消息
      socket.getInputStream().close();
    } catch (SSLException e) {
      // 捕获并处理SSLException
      if (!"closing inbound before receiving peer's close_notify".equals(e.getMessage())) {
            throw e;
      }
    }

在上述代码中,通过捕获`SSLException`,并检查错误消息内容,忽略特定的错误,从而确保程序不会因为未接收到`close_notify`消息而中断。

4. 总结

通过本文的介绍,我们详细了解了`javax.net.ssl.SSLException: closing inbound before receiving peer‘s close_notify`错误的原因及解决方案。无论是通过正确关闭SSL连接,还是捕获并处理异常,都可以有效地解决该错误。在实际开发中,了解并掌握这些技巧,可以帮助我们编写更健壮的网络程序,避免因SSL/TLS相关问题导致的程序中断。希望本文的介绍能够帮助大家解决这一常见的SSL错误,更好地进行Java网络编程。






------------------------------------------------------------------------------------------------------------------------------------------
========御 坂 主 机========
>> VPS主机 服务器 前沿资讯 行业发布 技术杂谈 <<
>> 推广/合作/找我玩TG号 : @Misaka_Offical <<
-------------------------------------------------------------------------------------------------------------------------------------------
页: [1]
查看完整版本: javax.net.ssl.SSLException:closing inbound before receiving peer‘s close_notify