简易Web服务器实现

Posted JobsandCzj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简易Web服务器实现相关的知识,希望对你有一定的参考价值。

手痒就自己实现了一下简易的web服务器,由于只是简易的web服务器,所以并没有什么特别高深的技术含量。

1.      TCP通信(socket)

2.      IO流

3.      线程池技术

服务器架构也简单:


Request类主要是实现解析URL的功能,以获取html文件的路径。

Response类实现读取html文件并且向浏览器输出html文件内容。

Server类整合Request类和Response类,实现线程的run方法。

Test类实现线程池,同时也是服务启动类。

下图是浏览器发给服务器的内容:


下面是效果图:

1.服务器输出的日志


页面效果图:


下面贴一些关键代码:

package request;

import java.io.BufferedReader;
import java.io.IOException;

public class Request {
	private String fileroute=null;
	private BufferedReader br=null;
	
	public Request(BufferedReader br) {
		this.br=br;
	}
	public void parse(){
		
		String info=null;
		StringBuffer msg=new StringBuffer();
		try {
			
			while((info=br.readLine())!=null && info.length()>0){//循环读取客户端的信息
				msg.append(info);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		fileroute=parseFileroute(msg.toString());
	}
	//由浏览器发给服务器内容的规律进行读取文件路径
	private String parseFileroute(String requestString) {
        int index1, index2;
        index1 = requestString.indexOf(' ');
        if (index1 != -1) {
            index2 = requestString.indexOf(' ', index1 + 1);
            if (index2 > index1)
                return requestString.substring(index1 + 1, index2);
        }
        return null;
    }
	//获取html文件名
	public String getFileroute(){
		return fileroute;
	}
}

package response;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class Response {
	private PrintWriter pw=null;
	private String fileroute=null;
	
	public Response(PrintWriter pw, String fileroute) {
		this.pw=pw;
		this.fileroute=fileroute;
	}
	
	public void doresponse() {
		File file=new File("webapp"+fileroute);
//		System.out.println(file.getAbsolutePath());
		if(!file.exists() || !file.isFile()) //不是文件或不存在
			return;
		
		FileInputStream is=null;
		InputStreamReader isr=null;
		BufferedReader br=null;
		
		try {
			is=new FileInputStream(file);
			isr=new InputStreamReader(is);
			br=new BufferedReader(isr);
			String info;
			StringBuffer msg=new StringBuffer();
			while((info=br.readLine())!=null && info.length()>0){//循环读取html文件内容
				msg.append(info);
			}
			//将文件内容输出到浏览器
			pw.write(msg.toString());
			pw.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			//关闭资源
			try {
				if(br!=null)
					br.close();
				if(isr!=null)
					isr.close();
				if(is!=null)
					is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}

package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

import request.Request;
import response.Response;

/*
 * 基于TCP协议的Socket通信,实现用户登陆
 * 服务器端
 */
public class Server implements Runnable {
	private Socket socket=null;
	public Server(Socket socket) {
		this.socket=socket;
	}
	
	@Override
	public void run() {
		System.out.println(Thread.currentThread().getName()); //输出当前线程名字
		InputStream is=null;
		InputStreamReader isr=null;
		BufferedReader br=null;
		OutputStream os=null;
		PrintWriter pw=null;
		//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
		try {
			
			//接收请求 进入阻塞状态
			InetAddress address=socket.getInetAddress();
			System.out.println("当前客户端的IP:"+address.getHostAddress());
			System.out.println("当前客户端端口:" + socket.getPort());
			
			is=socket.getInputStream();
			isr=new InputStreamReader(is);
			br=new BufferedReader(isr);
			
			Request request = new Request(br);
			request.parse();
			
			os = socket.getOutputStream();
			pw = new PrintWriter(os);
			Response response = new Response(pw, request.getFileroute());
			response.doresponse();
		} catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {
			//关闭资源
			try {
				if(pw!=null)
					pw.close();
				if(os!=null)
					os.close();
				if(br!=null)
					br.close();
				if(isr!=null)
					isr.close();
				if(is!=null)
					is.close();
				if(socket!=null)
					socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

package test;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import server.Server;

public class Test {

	public static void main(String[] args) {
		ExecutorService pool=null;
		ServerSocket serverSocket=null;
		try {
			serverSocket=new ServerSocket(80);
			// 创建一个可重用固定线程数的线程池 线程数为5
		    pool = Executors.newFixedThreadPool(5);
			Socket socket=null;
			while(true) {
				socket=serverSocket.accept();
				
//				new Thread(new Server(socket)).start();
				pool.execute(new Server(socket));
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(pool!=null)
				pool.shutdown();
			try {
				if(serverSocket!=null)
					serverSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

一个不错的练手项目,涉及到JAVA的IO,Socket,多线程,大家都可以试着实现一下。



以上是关于简易Web服务器实现的主要内容,如果未能解决你的问题,请参考以下文章

简易Web服务器实现

Tinywebserver:一个简易的web服务器

一个简易的web服务器:Tinywebserver

Python实现简易Web服务器

Python实现简易HTTP服务器与MINI WEB框架(利用WSGI实现服务器与框架解耦)

用 Web 实现一个简易的音频编辑器