我正在编写一个Web编程类的第一个家庭作业项目,即用Java编写一个简单的Web服务器。我正处于数据来回传输的地步,对于未经训练的眼睛,我的婴儿服务器似乎工作正常。但是,我找不到发送适当回复的方法。 (换句话说,无效页面请求将显示404-ish HTML页面,但在查看响应标头时仍会返回200 OK状态)。
我仅限于能够使用标准网络库进行套接字管理和标准I / O库来读取和写入输入流中的字节和字符串。这是一些相关的代码:
从我的主...
ServerSocket servSocket = new ServerSocket(port, 10); // Bind the socket to the port
System.out.println("Opened port " + port + " successfully!");
while(true) {
//Accept the incoming socket, which means that the server process will
//wait until the client connects, then prepare to handle client commands
Socket newDataSocket = servSocket.accept();
System.out.println("Client socket created and connected to server socket...");
handleClient(newDataSocket); //Call handleClient method
}
从handleClient方法...(在解析请求方法和路径的循环内)
if(checkURL.compareTo("/status") == 0) { // Check to see if status page has been requested
System.out.println("STATUS PAGE"); // TEMPORARY. JUST TO MAKE SURE WE ARE PROPERLY ACCESSING STATUS PAGE
sendFile("/status.html", dataStream);
}
else {
sendFile(checkURL, dataStream); // If not status, just try the input as a file name
}
来自sendFile方法......
File f = new File(where); // Create the file object
if(f.exists() == true) { // Test if the file even exists so we can handle a 404 if not.
DataInputStream din;
try {
din = new DataInputStream(new FileInputStream(f));
int len = (int) f.length(); // Gets length of file in bytes
byte[] buf = new byte[len];
din.readFully(buf);
writer.write("HTTP/1.1 200 OK\r\n"); // Return status code for OK (200)
writer.write("Content-Length: " + len + "\r\n"); // WAS WRITING TO THE WRONG STREAM BEFORE!
writer.write("Content-Type: "+type+"\r\n\r\n\r\n"); // TODO VERIFY NEW CONTENT-TYPE CODE
out.write(buf); // Writes the FILE contents to the client
out.flush();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace(); // Not really handled since that's not part of project spec, strictly for debug.
}
}
else {
writer.write("HTTP/1.1 404 Not Found\r\n"); // Attempting to handle 404 as simple as possible.
writer.write("Content-Type: text/html\r\n\r\n\r\n");
sendFile("/404.html", sock);
}
任何人都能解释一下,在sendFile的条件中,我可以改变404块中的响应(就像我之前说的那样,响应头仍然显示200 OK)?这是我的废话,我只是想使用HTTPResponse类,但我不能。 (另外,如果f.exists == true,则不显示内容长度和类型。)
谢谢!
答案 0 :(得分:3)
编辑在我看来,就像在404情况下,你发送的内容是这样的:
HTTP/1.1 404 Not Found
Content-Type: text/html
HTTP/1.1 200 OK
Content-Length: 1234
Content-Type: text/html
...接下来是404页面。请注意404之后的200行。这是因为您的404处理正在调用sendFile
,它正在输出200响应状态代码。这可能会使收件人感到困惑。
遗漏了错误的答案:
HTTP响应以状态行开始,后跟(可选)一系列标头,然后(可选)包括响应主体。状态行和标题只是定义格式的行,如(选择随机示例):
HTTP/1.0 404 Not Found
要实现您的小型HTTP服务器,我建议您阅读the spec并查看响应应该是什么样子。这是一个概念上的飞跃,但它们实际上只是根据商定的格式返回的文本行。 (好吧,无论如何,这对我来说是一个概念上的飞跃。无论如何。我已经习惯了那些过于复杂的环境。)
从您最喜欢的命令行执行此类操作也很有帮助:
telnet www.google.com 80
GET /thispagewontbefound
...然后按Enter键。你会得到这样的东西:
HTTP/1.0 404 Not Found
Content-Type: text/html; charset=UTF-8
X-Content-Type-Options: nosniff
Date: Sun, 12 Sep 2010 23:01:14 GMT
Server: sffe
Content-Length: 1361
X-XSS-Protection: 1; mode=block
...后面跟着一些HTML来提供友好的404页面。上面的第一行是状态行,其余的是标题。状态行/标题与第一行内容(例如页面)之间有一个空行。
答案 1 :(得分:2)
您看到的问题很可能与您flush()
上遗失的writer
有关。根据您使用的Writer
类型,首先将字节写入需要刷新到流的缓冲区。这可以解释为什么输出中缺少Content-Length
和Content-Type
。在将其他数据写入流之前,只需将其刷新即可。
进一步致电sendFile("/404.html", sock);
。您没有在此处发布完整方法 - 但我认为您在sendFile
内递归调用它,从而为您的文件200 OK
发送/404.html
状态。
答案 2 :(得分:0)
根据您报告的症状,我认为真正的问题是您根本没有与您的服务器交谈!证据是1)您无法获得404响应,2)200响应没有内容长度和类型。如果您真的在谈论上面列出的代码,那么这些都不可能......
也许:
我建议您在代码的适当位置添加一些跟踪打印/日志记录,以确认它实际上已被调用。