java实现的HTTP简易服务器

来源:互联网 发布:淘宝美工招聘信息深圳 编辑:程序博客网 时间:2024/05/01 17:38

程序有点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 blocke.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();}}@Overridepublic 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 blocke.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\nDate 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\nDate 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\nDate 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 blocke.printStackTrace();} finally {try {connection.close();} catch (IOException e) {// TODO Auto-generated catch blocke.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";}}}



1 0
原创粉丝点击