测试我的简单HTTPS服务器的客户端

时间:2014-06-12 04:43:53

标签: java html java-ee

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

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

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

sample client

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

您可能需要让服务器以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请求,它以数据流的形式(例如utf8编码的字符)传递响应,我的webkit小部件呈现为HTML。
  2. 我填写HTML表单并通过actionmethod属性将数据作为网址编码字符串提交,就像普通的HTML表单一样。例如:
    • <form method="POST" action="process.php">
  3. 服务器接收数据并对其进行处理,然后再次返回字符流,但这次这些字符不代表HTML结构,而是JSON编码的对象。例如:
    • "{ 'response' : 1 }";
  4. 客户端现在接收该字符串,但不是尝试将这些字符表示为HTML结构,而是可以将它们解析为现在可以使用的Java对象。