【发布时间】:2014-06-13 20:15:13
【问题描述】:
经过一番努力,我终于能够用 Java 编写一个简单的 HTTPS 服务器来处理 HTTPS 请求。我最终应该做的是从表单中获取数据,处理它,然后返回结果。作为开始,在这个简单的示例中,我只想返回提交选项的“值”。不幸的是,当我打印服务器收到的内容时,除了POST /run.html HTTP/1.1 之外,我没有看到任何 POST 数据。有什么问题,如何添加此功能?
PS:如果你想测试,不要忘记为 SSL 创建一个密钥库并将信息写入代码中。
我得到的 POST 请求是这样的(即使长度是 41,我想对于 list=capacity.3Mbps_400RTT_PER_0.0001.txt 的缺失数据应该是正确的):
POST /run.html HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Referer: https://localhost:8888/
Accept-Language: en-US
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: localhost:8888
Content-Length: 41
Connection: Keep-Alive
Cache-Control: no-cache
这是我在 HTML 中的简单表单(实际上我应该从服务器接收它的 HTML 源):
<html><body>
<p>
<h3> Please select a configuration below to run the emulator.</h3>
<form action="run.html" method="POST">
<select name="list">
<option name="400" value="capacity.3Mbps_400RTT_PER_0.0001.txt">capacity.3Mbps_400RTT_PER_0.0001</option>
<option name="100" value="capacity.3Mbps_100RTT_PER_0.00001.txt">capacity.3Mbps_100RTT_PER_0.00001</option>
<option name="200" value="capacity.3Mbps_200RTT_PER_0.0001.txt">capacity.3Mbps_200RTT_PER_0.0001</option>
</select>
<input type="submit" value="Run Emulator!">
</form>
</body></html>
这是我的 Java HTTPS 服务器程序:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
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 HttpsServer {
public static void main(String[] args) {
String ksName = "myJKS.jks";
char ksPass[] = "key".toCharArray();
char ctPass[] = "key".toCharArray();
try {
// Runtime.getRuntime().exec("notepad");
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,0, null);
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);
// w.write(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");
//should be two new lines!!!
w.newLine();
w.newLine();
if(m.contains("GET"))
//read from file
MyFileReader(w,"index.html");
while ((m = r.readLine()) != null) {
if (m.length() == 0)
break; // End of a GET call
// w.write(m);
System.out.println(m);
w.newLine();
}
w.flush();
}
w.close();
r.close();
c.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void MyFileReader(BufferedWriter w, String uri) {
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(uri));
while ((sCurrentLine = br.readLine()) != null) {
w.write(sCurrentLine);
System.out.println(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (br != null)
br.close();
} catch (IOException ex) {
ex.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());
}
}
【问题讨论】:
-
您的请求的第二行可以为空吗?如果您的内部 while 循环并且不打印出任何其他行,那将导致您进入内部。
-
不,我不这么认为。当它不为null并且是post方法时,它会进入循环内部,我会得到结果。
-
@jlars62 我只是在检查,没有......在 POST /run.html HTTP/1.1 之后我没有表单的数据。
-
在标题之后和响应正文之前有一个空行。而且因为那行是空白的,所以你正在打破你的内部 while 循环。只需尝试删除它,看看会发生什么
if (m.length() == 0) break; // End of a GET call -
是的;这就是我所做的。似乎在那个空白行之后,有空而不是带数据!
标签: java html jakarta-ee post