java - 为什么 SSL 服务器套接字连接会在 Java 中阻塞,而非 SSL 服务器套接字不会?

标签 java sockets ssl sslsocketfactory

考虑一个线程上的非 SSL 套接字服务器和客户端的以下代码:

import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerClient {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(0); // open a random free port.

        Socket c = new Socket(ss.getInetAddress(), ss.getLocalPort());

        Socket s = ss.accept();

        final byte[] bytes = "Hello World!".getBytes();
        final OutputStream out = c.getOutputStream();
        System.out.println("writing to stream");
        out.write(bytes.length);
        out.write(bytes);

        System.out.println("reading from stream");

        final DataInputStream in = new DataInputStream(s.getInputStream());
        int len = in.read();
        final byte[] b = new byte[len];
        in.readFully(b);
        System.out.println(new String(b));

        c.close();
        ss.close();
    }
}

这会产生以下输出:

writing to stream
reading from stream
Hello World!

这个进程打开了一个服务器套接字——连接到一个客户端套接字。将数据传递到套接字,然后关闭。传递数据没有问题。

考虑一个版本来证明 SSL 套接字的意义:

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.logging.Logger;

public class SSLServerClient {

    private static Logger log = Logger.getLogger("InfoLogging");

    public static void main(String[] args) throws IOException {

        System.setProperty("javax.net.ssl.keyStore", "/path/KeyStore.jks");
        System.setProperty("javax.net.ssl.keyStorePassword", "password");

        SSLServerSocketFactory sslserversocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();

        SSLServerSocket serverListeningSSLSocket = (SSLServerSocket) sslserversocketfactory.createServerSocket(4380);
        log.info("Server started");

        SSLSocketFactory sslSocketFactory=(SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket clientSocket =  (SSLSocket) sslSocketFactory.createSocket(serverListeningSSLSocket.getInetAddress(),
                serverListeningSSLSocket.getLocalPort());

        SSLSocket serverCommsSSLSocket = (SSLSocket) serverListeningSSLSocket.accept();
        log.info("new client");

        final byte[] bytes = "Hello World!".getBytes();
        final OutputStream out = clientSocket.getOutputStream();
        System.out.println("writing to stream");
        out.write(bytes.length);
        out.write(bytes);

        System.out.println("reading from stream");

        final DataInputStream in = new DataInputStream(serverCommsSSLSocket.getInputStream());
        int len = in.read();
        final byte[] b = new byte[len];
        in.readFully(b);
        System.out.println(new String(b));

        clientSocket.close();
        serverCommsSSLSocket.close();
        serverListeningSSLSocket.close();
    }
}

这给出了以下输出:

Nov 21, 2018 10:23:51 PM com.gamble.ssl.SSLServerClient main INFO: Server started
Nov 21, 2018 10:23:52 PM com.gamble.ssl.SSLServerClient main INFO: new client
writing to stream

即它在服务器套接字启动时阻塞。

我的问题是:为什么 Java 中的 SSL 服务器套接字连接会阻塞,而非 SSL 服务器套接字则不会?

最佳答案

什么是“翻转明文”?什么意思?

这是你正在做的:

  • 创建 SSL 服务器套接字
  • 创建连接到 SSL 服务器套接字的普通套接字
  • 从客户端发送一些数据
  • 在服务器端读取一些数据

现在,SSL 套接字需要加密数据传输。但是您未发送的数据未加密,因此它不是有效的 SSL 并且会引发异常 - 正如它所说,“无法识别的 SSL 消息”因为您没有发送有效的 SSL 消息和“纯文本连接?”是关于可能出错的提示。

您必须在连接的两端都使用 SSL,否则它们无法正确地相互通信。

关于java - 为什么 SSL 服务器套接字连接会在 Java 中阻塞,而非 SSL 服务器套接字不会?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53373183/

相关文章:

ssl - 基于ip的ssl证书

java - 未使用CSS样式且未读取列表

java - 添加库后不断收到错误 Gradle Build 失败,出现异常 : java. exe' 以非零退出值 2 完成

java - 从 .jasper 文件获取 JasperPrint 对象

java - 使用套接字的客户端-服务器-客户端通信

python - 如何使用 Python 从 HTTP 响应中获取端口号?

php - 无法识别本地发行人

tomcat - TLS_RSA_WITH_AES_128_CBC_SHA 和 SSL_RSA_WITH_AES_128_CBC_SHA

java - 检测日期是否更改的最有效方法是什么?

java - Android TCP套接字客户端/服务器实现