我在家里主持一个网页。我使用Java创建了自己的HTTP服务器。这是一个SSCCE:
if(command.startsWith("GET"))
{
//client is a socket on which I reply.
PrintWriter pw = new PrintWriter(client.getOutputStream(), true);
String commule = command.split(" ");
if(commule[0].equals("GET"))
{
if(commule[1].contains("."))
{
File file = new File(GEQO_SERVER_ROOT + commule[1].substring(1).replaceAll("%20", " "));
if(file.exists())
{
OutputStream out = client.getOutputStream();
InputStream stream = new FileInputStream(file);
String response = new String();
response += "HTTP/1.1 200 OK\r\n";
response += "Date: Thu, 08 Aug 2013 08:49:37 GMT\r\n";
response += "Content-Type: text/html\r\n";
response += "Content-Length: " + file.length() + "\r\n";
response += "Connection: keep-alive\r\n";
response += "\r\n";
pw.write(response); //Assume I already initialized pw as a PrintWriter
pw.flush();
copy(stream, out);
stream.close();
out.close();
}
else
{
pw.write("<html><h1>The request 404ed.</h1>");
pw.write("<body>The requested URL <b>" + commule[1] + "</b> could not be found on this server.</body></html>");
pw.flush();
}
}
else
{
BufferedReader br = new BufferedReader(new FileReader(GEQO_SERVER_ROOT + commule[1].substring(1) + "main.html"));
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null)
{
pw.print(sCurrentLine);
}
br.close();
}
}
else
{
pw.println("Unrecognized HTTP command.");
}
}
这是main.html来源:
<html>
<title>Geqo Server</title>
<body>Geqo server online and functioning!</body>
</html>
问题在于,当我尝试使用Chrome访问此页面时,它会正确显示(至少在使用127.0.0.1时)。但是当我尝试在127.0.0.1上的Firefox上访问它时,它可以工作,但只是给了我html源代码。 IE也只给我源。谁能告诉我为什么Firefox和IE只显示源代码而不是解析它?
我认为这包含一些线索(Firebug截图):
我的来源似乎是<pre>
标签。我不知道为什么,但不是那种问题吗?
我端口转发。这是页面人员:http://110.172.170.83:17416/
(对不起,Stackoverflow不允许数字链接。)
if
上的if(commule[1].contains("."))
语句导致代码跳过这里的大部分代码。在相应的else
块中,甚至没有命令来发送标头。感谢artbristol指出了这一点。
提前致谢。
答案 0 :(得分:5)
你的printwriter没有刷新(正如Ernest指出的那样),所以没有发送HTTP头。查看直接连接的结果 - 它只返回原始数据,没有标题。
nc 110.172.170.83 17416
GET /
<html><title>Geqo Server</title><body>Geqo server online and functioning!</body></html>
编写HTTP服务器是努力工作。除非这是练习,否则您应该使用轻量级的现有应用程序,例如Jetty,或JDK中内置的Sun HTTP服务器。
编辑 - PrintWriter
真的不适合做HTTP。它旨在处理逐行数据,例如写入磁盘的文件。它还依赖于文本编码和行结尾的特定于平台的设置。检查HTTP spec以获取有关正确的HTTP服务器应如何工作的更多详细信息。
答案 1 :(得分:1)
缓冲似乎存在一些潜在问题。您将部分输出写入PrintWriter
的{{1}}包装,并将其他输出直接写入out
。我绝对会在out
电话后添加pw.flush()
电话。
答案 2 :(得分:1)
您使用
的第二个参数启用了autoFlush
new PrintWriter(client.getOutputStream(), true)
http://docs.oracle.com/javase/7/docs/api/java/io/PrintWriter.html
与PrintStream类不同,如果启用了自动刷新,则只有在调用println,printf或format方法之一时才会执行,而不是每当输出换行符时。这些方法使用平台自己的行分隔符概念而不是换行符。
所以基本上你的pw.write()
没有刷新到输出流。所以你需要做的就是替换
pw.write(response);
与
pw.println(response);
答案 3 :(得分:0)
您不发送任何回复标题。
我在源代码中找不到pw
的定义?