如何配置 Java SSL 客户端套接字使其表现得像 Python?

问题描述 投票:0回答:1

我正在尝试使用 SSL 包装应用程序 TCP 数据以将数据传输到具有 TLS 1.2 的服务器。

我可以用 Python 实现,但想用 Java 实现。我相信,我有用两种语言编写的在功能上相同的过程,但显然这里有些根本不同。

我在证书注册表中的 Windows 上安装了正确的证书。

我可以通过以下代码使用 Python 功能性地向服务器发送消息:

import socket
import ssl

HOST, PORT = 'server.com', 8000

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#sock.settimeout(10)

wrappedSocket = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1_2)#, ciphers="ADH-AES256-SHA")

# CONNECT AND PRINT REPLY
wrappedSocket.connect((HOST, PORT))

wrappedSocket.send(b"Hello")

wrappedSocket.close()

然而,在Java中,我可以完成握手,但实际上并没有传输任何消息。

这就是Java

...

String[] protocols = new String[]{"TLSv1.2"};
SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket)factory.createSocket("server.com", 8000);
socket.setEnabledProtocols(protocols);
socket.addHandshakeCompletedListener(new HandShakeListener(socket));
socket.startHandshake();

...

class HandShakeListener implements HandshakeCompletedListener{
             
     SSLSocket socket;
             
     public HandShakeListener(SSLSocket socket) {
          this.socket = socket;
                
     }

     @Override
     public void handshakeCompleted(HandshakeCompletedEvent arg0) {
          System.out.println("Handshake Completed");

          PrintWriter out;
      try {
           out = new PrintWriter(
                      new BufferedWriter(
                       new OutputStreamWriter(
                        socket.getOutputStream())));
      } catch (IOException e1) {
        e1.printStackTrace();
        return;
      }
          
          out.println("Hello from Java");
      System.out.println("Sending message");
      out.println();
      out.flush();
          out.close();
     }


我正在使用 JVM 参数

-Djavax.net.debug=all -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT

并且Djavax.net调试信息显示握手成功,正在写入数据。

我的理解是,在这种情况下,Python 和 Java 在功能上是相同的,但是当我从 Python 发送消息时,我在服务器上成功接收了消息,但是没有消息通过使用 Java 发送。

我错过了什么/这些之间有什么区别?

谢谢!

更新

根据要求,我已经不再使用事件侦听器,但是我现在只能在套接字关闭时向服务器发送数据。

            // Create an SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, null, null);
            SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // Connect to the server
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket("server.com", 8000); // Replace with your target server and port
            sslSocket.setEnabledCipherSuites(sslSocketFactory.getSupportedCipherSuites());
            sslSocket.setTcpNoDelay(true);

            // Perform SSL handshake
            sslSocket.startHandshake();

            // Send data to server
            OutputStream outputStream = sslSocket.getOutputStream();
            String message = "This is a test message";
            outputStream.write(message.getBytes());
            outputStream.flush();

            // Send more data to server
            String additionalMessage = "This is an additional message";
            outputStream.write(additionalMessage.getBytes());
            outputStream.flush();

            // Close the SSL socket when done
            sslSocket.close();

在服务器端,消息作为一个字符串接收,就好像“flush()”方法没有刷新缓冲区一样。

python java ssl tls1.2
1个回答
0
投票

如文档所述,OutputStream.flush() 什么都不做。你可以用 BufferedOutputStream 包装它来渗透你的请求。

这变成:

OutputStream outputStream = new BufferedOutputStream(sslSocket.getOutputStream(), 1024);
String message = "This is a test message";
outputStream.write(message.getBytes());
outputStream.flush();

// Send more data to server
String additionalMessage = "This is an additional message";
outputStream.write(additionalMessage.getBytes());
outputStream.flush();
© www.soinside.com 2019 - 2024. All rights reserved.