如何配置Java SSL客户端套接字以使其行为像Python一样?

wnavrhmk  于 2023-04-19  发布在  Java
关注(0)|答案(1)|浏览(105)

我正在尝试使用SSL Package 应用程序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()”方法没有刷新缓冲区一样。

aurhwmvo

aurhwmvo1#

如文档所示,OutputStream.flush()什么也不做,你可以用BufferedOutputStream Package 它来过滤你的请求。
这变成:

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();

相关问题