源码之下,了无秘密。两个类文件,WebServer.java;运行主线程,设置服务器监听端口,Processor.java根据http协议的规定,解析浏览器的请求,返回页面或错误。
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class WebServer { /** 默认使用的服务器Socket端口号 */ public static final int HTTP_PORT = 8080; private ServerSocket serverSocket; public void startServer(int port) { try { serverSocket = new ServerSocket(port); System.out.println("Web Server startup on " + port); while (true) { Socket socket = serverSocket.accept(); // 通过线程的方式来处理客户的请求 new Processor(socket).start(); } } catch (IOException e) { e.printStackTrace(); } } /** * WebServer类的启动方法,可以通过命令行参数指定当前Web服务器所使用的端口号。 */ public static void main(String[] argv) throws Exception { WebServer server = new WebServer(); if (argv.length == 1) { server.startServer(Integer.parseInt(argv[0])); } else { server.startServer(WebServer.HTTP_PORT); } } }
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; /** * 处理一个HTTP用户请求的线程类。 */ public class Processor extends Thread { private PrintStream out; private InputStream input; /** 默认的服务器存放访问内容的目录 */ public static final String WEB_ROOT = "d:\\java\\workspace\\test\\htdocs"; public Processor(Socket socket) { try { input = socket.getInputStream(); out = new PrintStream(socket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } public void run() { try { String fileName = parse(input); readFile(fileName); } catch (IOException e) { e.printStackTrace(); } } /** * 解析客户机发过的所有HTTP请求,如果是符合HTTP协议内容的, 就分析出客户机所要访问文件的名字,并且返回文件名。 */ public String parse(InputStream input) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(input)); String inputContent = in.readLine(); if (inputContent == null || inputContent.length() == 0) { sendError(400, "Client invoke error"); return null; } // 分析客户请求的HTTP信息,分析出到底想访问哪个文件, // 发过来的HTTP请求应该是三部分。 String request[] = inputContent.split(" "); if (request.length != 3) { sendError(400, "Client invoke error"); return null; } // 第一部分是HTTP状态码 String stateCode = request[0]; // 第二部分是请求的文件名 String fileName = request[1]; // 第三部分是HTTP版本号 String httpVersion = request[2]; System.out.println("State Code: " + stateCode + ", file name: " + fileName + ", HTTP version: " + httpVersion); return fileName; } /** * 处理调用一个文件的请求 */ public void readFile(String fileName) throws IOException { File file = new File(Processor.WEB_ROOT + fileName); if (!file.exists()) { sendError(404, "File Not Found"); return; } // 把文件的内容读取到in对象中。 InputStream in = new FileInputStream(file); byte content[] = new byte[(int) file.length()]; in.read(content); out.println("HTTP/1.0 200 sendFile"); out.println("Content-length: " + content.length); out.println(); out.write(content); out.flush(); out.close(); in.close(); } /** * 发送错误的信息 */ public void sendError(int errNum, String errMsg) { out.println("HTTP/1.0 " + errNum + " " + errMsg); out.println("Content-type: text/html"); out.println(); out.println("<html>"); out.println("<head><title>Error " + errNum + "--" + errMsg + "</title></head>"); out.println("<h1>" + errNum + " " + errMsg + "</h1>"); out.println("</html>"); out.println(); out.flush(); out.close(); } }