首页 > 代码库 > java实现的HTTP简易服务器

java实现的HTTP简易服务器

程序有点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 = http://www.mamicode.com/new byte[(int) theFile.length()];>


java实现的HTTP简易服务器