web服务器模拟实现

本文源于51cto。

直接上代码

/**
 * 山寨 WEB服务器 
 * 1: 支持多个 浏览器访问 (多线程) 
 * 2: 如何提供服务 (Socket) 
 * 3: 如何返回响应 (IO)
 * 
 * @author phenix
 *
 */
public class TomcatServer {

	// 默认端口
	private static int PORT = 8080;

	// 程序入口方法
	public static void main(String[] args) {
		// 动态设置服务器的端口(通过命令行传递)
		PORT = (null == args) ? PORT : Integer.parseInt(args[0]);
		new TomcatServer().start(PORT);
	}

	// 服务启动方法 创建Socket服务器
	public void start(int port) {
		try {
			System.out.println("---------监听[" + port + "]端口的服务器启动...---------");
			ServerSocket serverSocket = new ServerSocket(port);
			// 创建一个线程池,100表示最多维护100个线程为每个客户端服务
			ExecutorService pool = Executors.newFixedThreadPool(100);
			while (true) {
				Socket socket = serverSocket.accept();
				System.out.println("---------有客户端请求---------");
				// 将任务提交给线程池去处理
				pool.submit(new HandlerRequestThread(socket));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


/**
 * 专门处理不同的客户端请求的 多线程类
 * 
 * @author phenix
 *
 */
public class HandlerRequestThread implements Runnable {

	private InputStream in = null;
	// 因为要涉及浏览器内容的输出,所以使用了PrintStream 标准输出流
	private PrintStream out = null;

	// web 应用 根路径 E:\MyWeb\
	private static final String WEB_ROOT = "E:" + File.separator + "MyWeb"
			+ File.separator;

	// 通过构造器获得Socket
	// 并通过Socket获取对客户端的输入和输出流
	public HandlerRequestThread(Socket socket) {
		try {
			in = socket.getInputStream();
			out = new PrintStream(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// 解析请求头,获得客户端请求的资源名称
	private String parseRequestHead(InputStream in) throws IOException {
		// //客户端发起请求会将一些请求数据包含在请求头中(请求头的知识将在HTTP协议的课程中介绍)
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		// //请求头的第一行将 包含 请求的方式,请求的资源名称,请求的协议版本
		String headContent = br.readLine();
		// 通过观察发现数据是使用 空格 分割的
		String[] heads = headContent.split(" ");
		// 获取每一部分的数据,其实我们只要中间的请求资源名称 数据
		return heads[1].endsWith("/") ? "index.html" : heads[1];
	}

	// 根据 资源名称获取资源
	private void getFile(String fileName) throws IOException {
		File file = new File(WEB_ROOT + fileName);
		if (!file.exists()) {
			sendError("404", "您请求的资源[" + fileName + "]不存在!请确认一下");
		} else {
			BufferedInputStream fis = new BufferedInputStream(
					new FileInputStream(file));
			byte[] buffer = new byte[(int) file.length()];
			fis.read(buffer);

			// //告诉浏览器本次请求 正常成功 响应
			out.println("HTTP/1.1 200 OK");
			out.println();

			out.write(buffer);
			out.flush();
			out.close();
		}
	}

	// 输出错误信息
	private void sendError(String errorNumber, String errorMsg) {
		StringBuilder sb = new StringBuilder();
		sb.append("<html><head><title>错误页面</title>");
		sb.append("<meta http-equiv='Content-Type' content='text/html;charset='UTF-8'></head>");
		sb.append("<body>");
		sb.append("<center><h1><font color='red'>"+errorNumber+"</font></h1></center>");
		sb.append("<hr color='red'>");
		sb.append("<p>" + errorMsg + "</p>");
		sb.append("<img  src='images/a.jpg'>");
		sb.append("</body></html>");

		out.println("HTTP/1.1 400 Not Found");
		out.println();
		out.print(sb.toString());
		out.flush();
		out.close();
	}

	// 线程体方法
	@Override
	public void run() {
		String fileName;
		try {
			fileName = parseRequestHead(this.in);
			getFile(fileName);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值