【问题标题】:Test client for my simple HTTPS server我的简单 HTTPS 服务器的测试客户端
【发布时间】:2014-06-12 04:43:53
【问题描述】:

经过一番努力,我终于能够构建一个用 Java 实现的简单 HTTPS 示例服务器,如下所示。它接受客户端连接并发送回一段关于套接字信息的文本。所以到目前为止我有一个工作服务器示例;整洁。我如何使它成为双向连接,以使客户端也能够以交互模式发送/接收信息?我应该如何执行返回和前进的步骤?

基本上我希望在连接到服务器后在浏览器上显示这样的表单(这很容易;就像现在,我将发送与表单的 html 代码对应的文本)。但我需要客户端将填写好的数据发送回服务器。服务器会对这些原始数据做一些处理,并将结果返回给客户端显示。

PS:如果您想测试程序,请不要忘记创建密钥库证书并提供以下信息。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
public class HttpsEchoer {
   public static void main(String[] args) {
      String ksName = "myks.jks";
      char ksPass[] = "mypass".toCharArray();
      char ctPass[] = "mypass".toCharArray();
      try {
         KeyStore ks = KeyStore.getInstance("JKS");
         ks.load(new FileInputStream(ksName), ksPass);
         KeyManagerFactory kmf = 
         KeyManagerFactory.getInstance("SunX509");
         kmf.init(ks, ctPass);
         SSLContext sc = SSLContext.getInstance("TLS");
         sc.init(kmf.getKeyManagers(), null, null);
         SSLServerSocketFactory ssf = sc.getServerSocketFactory();
         SSLServerSocket s 
            = (SSLServerSocket) ssf.createServerSocket(8888);
         System.out.println("Server started:");
         printServerSocketInfo(s);
         // Listening to the port
         int count = 0;
         while (true) {
            SSLSocket c = (SSLSocket) s.accept();
            // Someone is calling this server
            count++;
            System.out.println("Connection #: "+count);
            printSocketInfo(c);
            BufferedWriter w = new BufferedWriter(
               new OutputStreamWriter(c.getOutputStream()));
            BufferedReader r = new BufferedReader(
               new InputStreamReader(c.getInputStream()));
            String m = r.readLine();
//            System.out.println(m);
            if (m!=null) {
               // We have a real data connection
               w.write("HTTP/1.1 200 OK");
               w.newLine();
               w.write("Content-Type: text/html");
               w.newLine();
               w.newLine();
               w.write("<html><body><pre>");
               w.newLine();
               w.write("Connection #: "+count);
               w.newLine();
               w.newLine();
               w.write(m);
               w.newLine();
               while ((m=r.readLine())!= null) {
                  if (m.length()==0) break; // End of a GET call
                  w.write(m);
                  w.newLine();
               }
               w.write("</pre></body></html>");
               w.newLine();
               w.flush();
            }     
            w.close();
            r.close();
            c.close();
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
   private static void printSocketInfo(SSLSocket s) {
      System.out.println("Server socket class: "+s.getClass());
      System.out.println("   Remote address = "
         +s.getInetAddress().toString());
      System.out.println("   Remote port = "
         +s.getPort());
      System.out.println("   Local socket address = "
         +s.getLocalSocketAddress().toString());
      System.out.println("   Local address = "
         +s.getLocalAddress().toString());
      System.out.println("   Local port = "
         +s.getLocalPort());
   }
   private static void printServerSocketInfo(SSLServerSocket s) {
      System.out.println("Server socket class: "+s.getClass());
      System.out.println("   Socker address = "
         +s.getInetAddress().toString());
      System.out.println("   Socker port = "
         +s.getLocalPort());
      System.out.println("   Need client authentication = "
         +s.getNeedClientAuth());
      System.out.println("   Want client authentication = "
         +s.getWantClientAuth());
      System.out.println("   Use client mode = "
         +s.getUseClientMode());
   } 
}

【问题讨论】:

    标签: java html jakarta-ee


    【解决方案1】:

    您的表单还应包含&lt;BUTTON type = "submit"...&gt; 用于发送填写的表单,&lt;FORM action="http://somesite..." method="post"&gt; 可让您确定在哪里以及如何发送。浏览器处理客户端(验证除外 - 您需要一些 JavaScript 代码或等效代码)。

    http://www.w3.org/ 的 HTML 4 或 5 规范包含大量示例。

    【讨论】:

    • 有一点我不确定:所以基本上服务器应该发送与表单对应的html文本,然后客户端填写并将数据发送回服务器(可以是JSON? )。然后服务器将结果以简单的 HTML 表单或 JSON 发送回,与客户端的 AJAX 混合?步骤有什么建议吗?
    • 为什么要使用 JSON?它必须使用一些客户端脚本来构建(参见另一个答案中的 process.php)。一个简单的查询字符串可以很容易地解析,例如stackoverflow.com/questions/13592236/…。然后,服务器程序可以发送另一个 HTML,带有或不带有另一个表单,等等。 - 简单的表单和查询对话框不需要 AJAX。 - OTOH,您可以深入研究脚本、JavaScript 或其他内容,并从中获得乐趣。
    【解决方案2】:

    您可能需要让服务器以 JSON 字符串或类似的形式发送响应,以便客户端接收、解析结果并相应地显示信息。这是我为接收服务器的响应(以 JSON 字符串的形式)然后打印结果(我懒得将其翻译成英文)所做的示例:

    package com.arielnmz;
    
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.net.URLConnection;
    
    import com.google.gson.Gson;
    
    public class JavaHttpRequestJSON {
        public static void main(String[] args) throws Exception {
            while (true) {
                new JavaHttpRequestJSON().testGet(new java.util.Random().nextInt());
                Thread.sleep(2000);
            }
        }
        private void testGet(int valor) throws Exception {
    
            // Crear URL
            URL url = new URL("http://localhost/http_req_test/server_script_json.php");
    
            // Establecer conexión
            URLConnection conexion = url.openConnection();
    
            // Enviaremos información
            conexion.setDoOutput(true);
    
            // Recibiremos respuesta
            conexion.setDoInput(true);
    
            // Establecer timeouts
            conexion.setConnectTimeout(5000);
            conexion.setReadTimeout(5000);
    
            // Usar caches: NO
            conexion.setUseCaches(false);
            conexion.setDefaultUseCaches(false);
    
            // Le decimos al servidor qué y cómo estamos enviando
            conexion.setRequestProperty("Content-Type", "application/json");
    
            // Creamos una instancia de nuestro "codificador" JSON
            String json;
            Gson gson = new Gson();
    
            // Creamos un objeto y lo codificamos como JSON
    //      Map<String, String> map = new HashMap<String, String>(); 
    //      map.put("valor", Integer.toString( num ) );
            ObjetoEnvio objetoEnvio = new ObjetoEnvio();
            objetoEnvio.setValor(valor);
    
            json = gson.toJson(objetoEnvio);
    
            System.out.println("Objeto en JSON: "+json+" / valor enviado "+objetoEnvio.getValor());
    
            DataOutputStream os = new DataOutputStream(conexion.getOutputStream());
            os.writeBytes(json);
            os.close();
    
            StringBuffer respuesta = new StringBuffer();
    
            BufferedReader in = new BufferedReader( 
                new InputStreamReader( conexion.getInputStream() )
            );
    
            String linea;
            while ((linea = in.readLine()) != null) {
                respuesta.append(linea);
            }
            in.close();
    
            ObjetoRespuesta respuesta_json = gson.fromJson(respuesta.toString(), ObjetoRespuesta.class);
    
    //      System.out.println(respuesta.toString());
            System.out.println(respuesta_json.getMensaje());
            System.out.println("Conexión finalizada");
        }
    
        private class ObjetoEnvio {
            private int valor;
            public void setValor(int valor) {
                this.valor = valor;
            }
            public int getValor() {
                return valor;
            }
        }
    
        private class ObjetoRespuesta {
            private String mensaje;
            public String getMensaje() { return mensaje; }
        }
    }
    

    更新

    这个答案基于这种方法:

    1. 我向服务器发送一个 HTTP 请求,它以我的 webkit 小部件呈现为 HTML 的数据流(例如 utf8 编码字符)的形式提供响应。
    2. 我填写 HTML 表单并通过 actionmethod 属性将数据作为 url 编码的字符串提交,就像普通的 HTML 表单一样。例如:
      • &lt;form method="POST" action="process.php"&gt;
    3. 服务器接收数据并对其进行处理,然后再次返回一个字符流,但这次这些字符不表示 HTML 结构,而是表示 JSON 编码的对象。例如:
      • "{ 'response' : 1 }";
    4. 客户端现在接收到该字符串,但您可以将这些字符解析为一个 Java 对象,而不是尝试将这些字符表示为 HTML 结构,您现在可以随意使用该对象。

    【讨论】:

    • 有一点我不确定:所以基本上服务器应该发送与表单对应的html文本,然后客户端填写并将数据发送回服务器(可以是JSON? )。然后服务器将结果以简单的 HTML 表单或 JSON 发送回,与客户端的 AJAX 混合?步骤有什么建议吗?
    • 这可能是一种方法。请参阅我使用的方法的更新答案。使用您的方法,您只需在步骤2 中将表单提交为JSON 对象而不是URL 编码字符串。没什么不同,它也可以工作。
    猜你喜欢
    • 2016-01-01
    • 2016-10-31
    • 2010-10-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    • 2014-10-17
    • 2015-12-29
    相关资源
    最近更新 更多