自己动手编写一个Web服务器

以下代码是我自己写的第一个Web服务器。它支持纯文本的英文字符的静态HTML页面。复制并将代码编译成.class文件后,运行它即可。它的监听端口是6789,网站根目录为C:\Inetpub,如果该目录下有一个test.html文件,那么,运行它后,在浏览器中输入:

http://localhost:6789/test.html,即可实现访问。

它还可以作为一个查看浏览器请求报文(HTTP请求报文)的工具,要实现这点,只需要在浏览器中输入一个并不存在的网页文件(如 http://localhost:6789/notexists.html),服务器程序便把客户端浏览器的请求报文回显出来。

源代码如下:

import java.io.*;
import java.net.*;

public class MyWebServer {
	public static String WebRoot = "C:\\Inetpub";
	
	/**
	 * 将虚拟路径转换成实际物理路径
	 * @param virtualPath
	 * @return
	 * @throws Exception
	 */
	private static String mapPath(String virtualPath) throws Exception {
		
		return WebRoot + virtualPath.replace("/", "\\");
	}
	
	private static String parseVirtualPathFromRequest(String request) throws Exception {
		return request.substring(4, request.indexOf(" HTTP/1.1"));
	}
	
	public static void main(String argv[]) throws Exception {
		// 客户端来的请求字符串
		String request;
		String requestLine;
		// 响应字符串
		String response;
		// HTML 模板
		String htmlTemplate = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/><title></title></head><body></body></html>";
		
		long count;
		
		// 显示启动信息
		printInfo("我的网页服务器启动了。");
		
		// 定义端口值
		int portNo;
		
		portNo = 6789;
		// 定义欢迎套接字
		ServerSocket welcomeSocket = new ServerSocket(portNo);
		// 输入信息
		printInfo("我的网页服务器在端口 " + portNo + " 处开启了一个欢迎套接字。");
		
		// 不断接收来自客户端的请求
		count = 0L;
		while (true) {
			// 建立新的连接套接字
			Socket connectionSocket = welcomeSocket.accept();
			if (connectionSocket != null) {
				printInfo("我的网页服务器收到来自客户端的请求,连接套接字已经建立。");
				BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
				DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

				request = "";
				response = "";
				requestLine = "";
				while (true) {					
					try {
						printInfo("我的网页服务器开始读入客户端的请求字符串……");
						requestLine = inFromClient.readLine();
						if (! requestLine.equals("")) {
							request += requestLine + "\n";
							printInfo("客户端请求:" + requestLine);
							if (request.contains("quit") || request.contains("exit")) {
								printInfo("客户端请求退出。");
							}

							if (request.contains("quit") || request.contains("exit")) {
								break;
							}
						} else {
							printInfo("客户端请求为空。我的网页服务器准备关闭该TCP连接。");
							// 关闭连接前,给予一个响应
							String filePath = mapPath(parseVirtualPathFromRequest(request));
							File file = new File(filePath);
							if (file.exists()) {
								FileReader myFile = new FileReader(filePath);
								BufferedReader myReader = new BufferedReader(myFile);
								String fileStream = myReader.readLine();
								while (fileStream != null) {
									response += fileStream + "\n";
									fileStream = myReader.readLine();
								}
								myReader.close();
								myFile.close();
							} else {
							
								response = htmlTemplate.replace("<title></title>", "<title>Response Frome MyWebServer</title>").replace("<body></body>", "<body><h1>Echo your request: </h1><pre>" + request + "</pre><p>You request " + filePath + ", which is not exists.</p></body>");
							}
							outToClient.writeBytes(response);
							printInfo("我的网页服务器响应: " + response);
							
							connectionSocket.close();
							break;
						}
					} catch (Exception e) {
						response = "退出" + "\n";
						printInfo("连接断开了,可能是客户端离开。详细信息为:\n" + e.toString());
						break;
					} finally {
					}
				} 
				printInfo("连接关闭了。");
				inFromClient.close();
				outToClient.close();
			} else {
				printInfo("我的网页服务器收到来自客户端的请求,但是连接套接字未能建立。");
			}
			connectionSocket.close();
		}		
	}
	
	/**
	 * 在控制板中输入信息
	 * @param info
	 * @throws Exception
	 */
	private static void printInfo(String info) throws Exception {
		System.out.println(info);
	}
}
 

Add comment

Loading