尝试一切,但它不起作用:(

完整的代码和示例可以在这里找到:https://examples.javacodegeeks.com/core-java/nio/java-nio-ssl-example/

您也可以通过单击此处下载完整的源代码(只有3个课程):https://examples.javacodegeeks.com/wp-content/uploads/2015/12/NioSSLExample.zip

谢谢你的帮助!

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;

public class NioSSLExample
{
   public static void main(String[] args) throws Exception
   {
      InetSocketAddress address = new InetSocketAddress("www.amazon.com", 443);
      Selector selector = Selector.open();
      SocketChannel channel = SocketChannel.open();
      channel.connect(address);
      channel.configureBlocking(false);
      int ops = SelectionKey.OP_CONNECT | SelectionKey.OP_READ;

      SelectionKey key =  channel.register(selector, ops);

      // create the worker threads
      final Executor ioWorker = Executors.newSingleThreadExecutor();
      final Executor taskWorkers = Executors.newFixedThreadPool(2);

      // create the SSLEngine
      final SSLEngine engine = SSLContext.getDefault().createSSLEngine();
      engine.setUseClientMode(true);
      engine.beginHandshake();
      final int ioBufferSize = 32 * 1024;
      final NioSSLProvider ssl = new NioSSLProvider(key, engine, ioBufferSize, ioWorker, taskWorkers)
      {
         @Override
         public void onFailure(Exception ex)
         {
            System.out.println("handshake failure");
            ex.printStackTrace();
         }

         @Override
         public void onSuccess()
         {
            System.out.println("handshake success");
            SSLSession session = engine.getSession();
            try
            {
               System.out.println("local principal: " + session.getLocalPrincipal());
               System.out.println("remote principal: " + session.getPeerPrincipal());
               System.out.println("cipher: " + session.getCipherSuite());
            }
            catch (Exception exc)
            {
               exc.printStackTrace();
            }

            //HTTP request
            StringBuilder http = new StringBuilder();
            http.append("GET / HTTP/1.0\r\n");
            http.append("Connection: close\r\n");
            http.append("\r\n");
            byte[] data = http.toString().getBytes();
            ByteBuffer send = ByteBuffer.wrap(data);
            this.sendAsync(send);
         }

         @Override
         public void onInput(ByteBuffer decrypted)
         {
            // HTTP response
            byte[] dst = new byte[decrypted.remaining()];
            decrypted.get(dst);
            String response = new String(dst);
            System.out.print(response);
            System.out.flush();
         }

         @Override
         public void onClosed()
         {
            System.out.println("ssl session closed");
         }
      };

      // NIO selector
      while (true)
      {
         key.selector().select();
         Iterator keys = key.selector().selectedKeys().iterator();
         while (keys.hasNext())
         {
            keys.next();
            keys.remove();
            ssl.processInput();
         }
      }
   }
}

最佳答案

        http.append("GET / HTTP/1.0\r\n");
        http.append("Connection: close\r\n");
        http.append("\r\n");


虽然从理论上讲,这实际上是正确的HTTP / 1.0请求,但是当今大多数系统都要求包含Host标头。尽管仅在HTTP / 1.1中这是强制性的,但如果IP地址承载多个域,则需要使用它:

        http.append("GET / HTTP/1.0\r\n");
        http.append("Host: www.amazon.com\r\n");
        http.append("\r\n");


还要注意,Connection: close是不必要的,因为它在HTTP / 1.0中是隐式的(但在HTTP / 1.1中不是)。

除此之外,HTTP比这个简单的请求要复杂得多,甚至这个请求也有您所看到的问题。如果您需要自己实现它,请研究标准,而不是假设服务器的反应方式或仅看几个例子。

07-25 23:52
查看更多