程序有点BUG,欢迎高手指点,为啥不同的浏览器差别这么大?
运行服务器端程序后,在浏览器分别输入如下请求路径观察效果(我的服务器资源默认路径设置的是F:/project目录)。
http://localhost
http://localhost/myfile.txt
/* * 模拟一个HTTP服务器的实现 * 客户端(浏览器)请求服务器的文件,服务器端程序接受连接并处理,将相应的数据写入socket,发送给客户端 * 本Web服务器将入站连接放入池中,由一个RequestProcessor类实例从池中移走连接并进行处理 */ import java.io.*; import java.net.*; public class JHTTP extends Thread{ private File documentRootDirectory; private String indexFileName="index.html"; private ServerSocket server; private int numThreads =50;//设置服务器启动的线程数 public JHTTP(File documentRootDirectory,int port,String indexFileName) throws IOException{ if(!documentRootDirectory.isDirectory()){ throw new IOException(documentRootDirectory+" does not exist as a directory"); } this.documentRootDirectory=documentRootDirectory; this.indexFileName=indexFileName; this.server=new ServerSocket(port); } public JHTTP(File documentRootDirectory,int port) throws IOException{ this(documentRootDirectory,port,"index.html"); } public JHTTP(File documentRootDirectory) throws IOException{ this(documentRootDirectory,80,"index.html"); } public void run(){ //开启处理请求的线程,该线程会从socket池中取出一个socket连接,进行数据传输 for(int i=0;i<numThreads;i++){ Thread t=new Thread(new RequestProcessor(documentRootDirectory, indexFileName)); t.start(); } System.out.println("Accepting connections on port "+server.getLocalPort()+"..."); System.out.println("Document Root:"+documentRootDirectory); //服务器不停地接受请求 while(true){ try { Socket connection=server.accept(); RequestProcessor.processRequest(connection); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[] args) { File docRoot;//得到文档根 docRoot=new File("F:\\project"); //设置服务器的监听端口 int port; port=80; try { JHTTP webServer=new JHTTP(docRoot,port); webServer.start(); } catch (IOException e) { System.out.println("Server could not start because of an "+e.getClass()); System.out.println(e); } } }
//具体处理连接的线程类 import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import java.io.*; import java.net.Socket; public class RequestProcessor implements Runnable { private static List pool = new LinkedList(); private File documentRootDirectory; private String indexFileName = "index.html"; public RequestProcessor(File documentRootDirectory, String indexFileName) { if (documentRootDirectory.isFile()) { throw new IllegalArgumentException( "documentRootDirectory must be a directory,not a file"); } this.documentRootDirectory = documentRootDirectory; // 返回此抽象路径名的规范形式 try { this.documentRootDirectory = documentRootDirectory .getCanonicalFile(); } catch (IOException e) { System.out.println(e); } if (indexFileName != null) { this.indexFileName = indexFileName; } } public static void processRequest(Socket request) { // 将对应于每一个客户端的socket连接放入池中,通知线程来处理他们 synchronized (pool) { pool.add(pool.size(), request); pool.notifyAll(); } } @Override public void run() { // 执行安全性检查,请求的文档不能超过根目录 String root = documentRootDirectory.getPath(); // 由于采用线程池的策略,所以说线程要不停地执行,以处理客户端的请求池(socket池)中的连接 while (true) { Socket connection; synchronized (pool) { while (pool.isEmpty()) { try { pool.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } connection = (Socket) pool.remove(0); } // 通过socket这个中介进行服务器客户端的数据交换 try { OutputStream raw; raw = new BufferedOutputStream(connection.getOutputStream()); Writer out = new OutputStreamWriter(raw); Reader in = new InputStreamReader(new BufferedInputStream( connection.getInputStream()), "ASCII"); // 存储客户端请求的第一行数据 StringBuffer requestLine = new StringBuffer(); int c; while (true) { c = in.read(); if (c == '\r' || c == '\n') break; requestLine.append((char) c); } String get = requestLine.toString(); System.out.println(get);// 记录请求的头一行(要对头行进行一些分解,如下) StringTokenizer st = new StringTokenizer(get); String method = st.nextToken(); String version = ""; // 本案例目前只处理GET请求 String filename; String contentType; if (method.equals("GET")) { filename = st.nextToken(); if (filename.endsWith("/")) filename += indexFileName; contentType = guessContentTypeFromName(filename); if (st.hasMoreTokens()) { version = st.nextToken(); } File theFile = new File(documentRootDirectory, filename.substring(1, filename.length())); if (theFile.canRead() && theFile.getCanonicalPath().startsWith(root)) { DataInputStream fis = new DataInputStream( new BufferedInputStream(new FileInputStream( theFile))); byte[] theData = new byte[(int) theFile.length()]; fis.readFully(theData); fis.close(); if (version.startsWith("HTTP ")) {// 发送MIME首部 out.write("HTTP/1.0 200 OK\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n Date now = new Date(); out.write("Date:" + now + "\r\n"); out.write("Server:JHTTP/1.0\r\n"); out.write("Content-Length:" + theData.length + "\r\n"); out.write("Content-Type:" + contentType + "\r\n\r\n"); out.flush();// 切记结束的时候要刷新,写入缓冲区剩余数据 } // 发送实际请求的文件(可能是图片或其它二进制文件) raw.write(theData); raw.flush(); } else {// 无法找到文件 if (version.startsWith("HTTP ")) {// 发送MIME首部 out.write("HTTP/1.0 404 File Not Found ON MyServer\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n Date now = new Date(); out.write("Date:" + now + "\r\n"); out.write("Server:JHTTP/1.0\r\n"); out.write("Content-Type:text/html\r\n\r\n"); } out.write("<HTML>\r\n"); out.write("<HEAD><TITLE>File not found</TITLE>\r\n"); out.write("</HEAD>\r\n"); out.write("<BODY>"); out.write("<H1>HTTP Error 404:File not found\r\n"); out.write("</BODY></HTML>\r\n"); out.flush(); } } else {// 不是'GET'方法 if (version.startsWith("HTTP ")) {// 发送MIME首部 out.write("HTTP/1.0 501 Not Implemented\r\n");// HTTP协议规定的头格式,就是要求回车换行,就必须是\r\n Date now = new Date(); out.write("Date:" + now + "\r\n"); out.write("Server:JHTTP/1.0\r\n"); out.write("Content-Type:text/html\r\n\r\n"); } out.write("<HTML>\r\n"); out.write("<HEAD><TITLE>Not Implemented</TITLE>\r\n"); out.write("</HEAD>\r\n"); out.write("<BODY>"); out.write("<H1>HTTP Error 501:Not Implemented\r\n"); out.write("</BODY></HTML>\r\n"); out.flush(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { connection.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public static String guessContentTypeFromName(String name) { if (name.endsWith(".htm") || name.endsWith(".html")) { return "text/html"; } else if (name.endsWith(".txt") || name.endsWith(".java")) { return "text/plain"; } else if (name.endsWith(".class")) { return "application/octet-stream"; } else if (name.endsWith(".gif")) { return "image/gif"; } else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) { return "image/jpeg"; } else if (name.endsWith(".mp3")) { return "audio/mpeg"; } else { return "text/plain"; } } }
时间: 2024-10-10 22:20:11