返回带有Java Web服务器的文件时出错
我用Java编写的这个基本、简单的Web服务器遇到了麻烦。出于某种原因,不是将“200 OK”或“404 Not Found”单独发送到浏览器,而是将它们写入正在检索的任何文件中。例如,如果我尝试获取index.html文件,则返回: …而不是浏览器试图编译HTML。 当试图获取图像时,情况更糟,因为服务器试图将“200OK”和内容类型附加到该文件时,该文件已损坏。有人能提供一些见解,说明如何将状态行和内容类型与实际的HTML/JPG文件分开发送吗?当我注释掉“os.writeBytes(statusLine)”等时,错误完全消失了,但我仍然希望将这些消息发送到浏览器…只是不与文件合并。任何帮助都将不胜感激返回带有Java Web服务器的文件时出错,java,multithreading,io,webserver,outputstream,Java,Multithreading,Io,Webserver,Outputstream,我用Java编写的这个基本、简单的Web服务器遇到了麻烦。出于某种原因,不是将“200 OK”或“404 Not Found”单独发送到浏览器,而是将它们写入正在检索的任何文件中。例如,如果我尝试获取index.html文件,则返回: …而不是浏览器试图编译HTML。 当试图获取图像时,情况更糟,因为服务器试图将“200OK”和内容类型附加到该文件时,该文件已损坏。有人能提供一些见解,说明如何将状态行和内容类型与实际的HTML/JPG文件分开发送吗?当我注释掉“os.writeBytes(st
import java.io.*;
import java.net.*;
import java.util.*;
final class HttpRequest implements Runnable {
final static String CRLF = "\r\n";
Socket socket;
// Constructor
public HttpRequest(Socket socket) throws Exception {
this.socket = socket;
}
// Implement the run() method of the Runnable interface.
public void run() {
try {
processRequest();
} catch (Exception e) {
System.out.println(e);
}
}
private static void sendBytes(FileInputStream fis, OutputStream os)
throws Exception {
// Construct a 1K buffer to hold bytes on their way to the socket.
byte[] buffer = new byte[1024];
int bytes = 0;
// Copy requested file into the socket's output stream.
while((bytes = fis.read(buffer)) != -1 ) {
os.write(buffer, 0, bytes);
}
}
private static String contentType(String fileName) {
if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {
return "text/html";
}
if(fileName.endsWith(".jpeg") || fileName.endsWith(".jpg")) {
return "image/jpeg";
}
if(fileName.endsWith(".gif")) {
return "image/gif";
}
return "application/octet-stream";
}
private void processRequest() throws Exception {
// Get a reference to the socket's input and output streams.
InputStream is = socket.getInputStream();
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
// Set up input stream filters.
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// Get the request line of the HTTP request message.
String requestLine = new String(br.readLine());
// Display the request line.
System.out.println();
System.out.println(requestLine);
// Get and display the header lines.
String headerLine = null;
while ((headerLine = br.readLine()).length() != 0) {
System.out.println(headerLine);
}
// Extract the filename from the request line.
StringTokenizer tokens = new StringTokenizer(requestLine);
tokens.nextToken(); // skip over the method, which should be "GET"
String fileName = tokens.nextToken();
// Prepend a "." so that file request is within the current directory.
fileName = "." + fileName;
// Open the requested file.
FileInputStream fis = null;
boolean fileExists = true;
try {
fis = new FileInputStream(fileName);
} catch (FileNotFoundException e) {
fileExists = false;
}
// Construct the response message.
String statusLine = null;
String contentTypeLine = null;
String entityBody = null;
if (fileExists) {
statusLine = "200 OK" + CRLF;
contentTypeLine = "Content-type: " +
contentType( fileName ) + CRLF;
} else {
statusLine = "404 NOT FOUND" + CRLF;
contentTypeLine = "Content Not Found!" + CRLF;
entityBody = "<HTML>" +
"<HEAD><TITLE>Not Found</TITLE></HEAD>" +
"<BODY>Not Found</BODY></HTML>";
}
// Send the status line.
os.writeBytes(statusLine);
// Send the content type line.
os.writeBytes(contentTypeLine);
// Send a blank line to indicate the end of the header lines.
os.writeBytes(CRLF);
// Send the entity body.
if (fileExists) {
sendBytes(fis, os);
fis.close();
} else {
os.writeBytes("File DNE: Content Not Found!");
}
// Close streams and socket.
os.close();
br.close();
socket.close();
}
public static void main(String[] args) throws Exception {
final ServerSocket ss = new ServerSocket(6789);
while (true)
new HttpRequest(ss.accept()).run();
}
}
import java.io.*;
导入java.net。*;
导入java.util.*;
最后一个类HttpRequest实现Runnable{
最终静态字符串CRLF=“\r\n”;
插座;
//建造师
公共HttpRequest(套接字)引发异常{
this.socket=socket;
}
//实现Runnable接口的run()方法。
公开募捐{
试一试{
processRequest();
}捕获(例外e){
系统输出打印ln(e);
}
}
私有静态void sendBytes(FileInputStream fis、OutputStream os)
抛出异常{
//构造一个1K缓冲区,在字节到达套接字的过程中保存字节。
字节[]缓冲区=新字节[1024];
int字节=0;
//将请求的文件复制到套接字的输出流中。
而((字节=fis.read(缓冲区))!=-1){
写操作(缓冲区,0,字节);
}
}
私有静态字符串contentType(字符串文件名){
if(fileName.endsWith(“.htm”)| | fileName.endsWith(“.html”)){
返回“text/html”;
}
if(fileName.endsWith(“.jpeg”)| | fileName.endsWith(“.jpg”)){
返回“图像/jpeg”;
}
if(fileName.endsWith(“.gif”)){
返回“image/gif”;
}
返回“应用程序/八位字节流”;
}
私有void processRequest()引发异常{
//获取对套接字的输入和输出流的引用。
InputStream=socket.getInputStream();
DataOutputStream os=新的DataOutputStream(socket.getOutputStream());
//设置输入流过滤器。
BufferedReader br=新的BufferedReader(新的InputStreamReader(is));
//获取HTTP请求消息的请求行。
String requestLine=新字符串(br.readLine());
//显示请求行。
System.out.println();
System.out.println(请求行);
//获取并显示标题行。
字符串标题行=null;
while((headerLine=br.readLine()).length()!=0){
系统输出打印LN(车头线);
}
//从请求行提取文件名。
StringTokenizer令牌=新的StringTokenizer(requestLine);
tokens.nextToken();//跳过该方法,该方法应为“GET”
字符串文件名=tokens.nextToken();
//在“.”前面加上前缀,使文件请求位于当前目录中。
fileName=“.”+文件名;
//打开请求的文件。
FileInputStream fis=null;
布尔fileExists=true;
试一试{
fis=新文件输入流(文件名);
}catch(filenotfounde异常){
fileExists=false;
}
//构造响应消息。
字符串statusLine=null;
字符串contentTypeLine=null;
字符串entityBody=null;
如果(文件存在){
statusLine=“200正常”+CRLF;
contentTypeLine=“内容类型:”+
contentType(文件名)+CRLF;
}否则{
statusLine=“404未找到”+CRLF;
contentTypeLine=“找不到内容!”+CRLF;
entityBody=”“+
“找不到”+
“未找到”;
}
//发送状态行。
操作系统写入字节(状态行);
//发送内容类型行。
写字节(contentTypeLine);
//发送一个空行以指示标题行的结尾。
操作系统写入字节(CRLF);
//发送实体体。
如果(文件存在){
sendBytes(fis、os);
fis.close();
}否则{
os.writeBytes(“文件DNE:未找到内容!”);
}
//关闭流和套接字。
os.close();
br.close();
socket.close();
}
公共静态void main(字符串[]args)引发异常{
最终服务器插座ss=新服务器插座(6789);
while(true)
新的HttpRequest(ss.accept()).run();
}
}
我相信您丢失了一个CRLF。在状态行的末尾不需要额外的一个吗
200行
内容类型:xxxx
当然,您可以阅读HTTP规范,或者执行wireshark跟踪:)
更新:是的,你有很多问题。阅读一篇简单的文章
总结
但无论如何,你需要说“HTTP/1.0 200 OK”作为例子
http://www.somehost.com/path/file.html
首先打开主机www.somehost.com端口80的套接字(使用默认端口80,因为URL中未指定任何端口)。然后,通过套接字发送如下内容:
GET /path/file.html HTTP/1.0
From: someuser@jmarshall.com
User-Agent: HTTPTool/1.0
[blank line here]
服务器应通过相同的套接字发送以下响应:
HTTP/1.0 200 OK
Date: Fri, 31 Dec 1999 23:59:59 GMT
Content-Type: text/html
Content-Length: 1354
<html>
<body>
<h1>Happy New Millennium!</h1>
(more file contents)
.
.
.
</body>
</html>
HTTP/1.0 200正常
日期:1999年12月31日星期五23:59:59 GMT
内容类型:text/html
内容长度:1354
新千年快乐!
(更多文件内容)
.
.
.
在statusLine=“200正常”+CRLF
您没有正确的请求,您缺少HTTP/1.1
右代码:
if(文件存在){
statusLine=“HTTP/1.1 200正常”+CRLF;
contentTypeLine=“内容类型:”+
contentType(文件名)+CRLF+CRLF;
}否则{
statusLine=“404未找到”+CRLF;
contentTypeLine=“找不到内容!”+CRLF;
entityBody=”“+
“找不到”+
“未找到”;
}
我不太明白我在哪里会错过一个CRLF…我在状态行本身中有一个,以及在发送entit之前