用socket实现简单的http服务器功能

用最基本的socket实现http服务器的功能,上代码:

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

public class Webserver{
	//根资源路径	
	protected String docroot;
	//绑定端口,一般采用二级端口:8080
	protected int port;
	//监听scoket,监听请求
	protected ServerSocket ss;
	//内部类对象,用于处理一次请求
	class Handler extends Thread{
		protected PrintWriter pw;
		protected BufferedOutputStream bos;
		protected BufferedReader br;
		protected File docroot;  //所请求的资源
		protected Socket socket; //请求的链接

		public Handler(Socket _socket,String _docroot) throws Exception{
			this.socket=_socket;
			this.docroot=new File(_docroot).getCanonicalFile();
		}

		@Override
		public void run(){
			try{
				br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
				bos=new BufferedOutputStream(socket.getOutputStream());
				pw=new PrintWriter(new OutputStreamWriter(bos));

				String line=br.readLine();	//获得请求命令

				socket.shutdownInput();		//关闭输入链接,忽略接下来的数据。

				if(line == null){
					socket.close();
					return;
				}

				if(line.toUpperCase().startsWith("GET")){ //标准GET请求
					StringTokenizer tokens=new StringTokenizer(line," ?");
					tokens.nextToken(); 
					String req=tokens.nextToken();  //请求资源的相对路径
					String name; //请求资源的完整路径
					if(req.startsWith("/") || req.startsWith("\\")){
						name=this.docroot+req;
					}else{
						name=this.docroot+File.separator+req;
					}
					

					File file=new File(name).getCanonicalFile();

					//保证file的可访问性
					if(!file.getAbsolutePath().startsWith(this.docroot.getAbsolutePath())){
						pw.println("HTTP/1.0 403 Forbidden");
						pw.println();
					}else if(!file.exists()){
						pw.println("HTTP/1.0 404 File Not Found");
						pw.println();
					}else if(!file.canRead()){
						pw.println("HTTP/1.0 403 Forbidden");
						pw.println();
					}else if(file.isDirectory()){
						//请求的是文件夹
						sendDir(bos,pw,file,req);
					}else{
						//请求的是文件
						sendFile(bos,pw,file.getAbsolutePath());
					}
				}else{ 	//我们只实现了GET的请求方式
					pw.println("HTTP/1.0 501 Not Implemented");
					pw.println();
				}

				pw.flush();
				bos.flush();
			}catch(Exception e){
				e.printStackTrace();
			}
			try{
				socket.close();
			}catch(Exception x){
				x.printStackTrace();
			}
		}

		//相应文件的内容到浏览器
		protected void sendFile(BufferedOutputStream bos,PrintWriter pw,String fileName) throws Exception{
			try{
				BufferedInputStream bis=new BufferedInputStream(new FileInputStream(fileName));
				byte [] data= new byte[10*1024];
				int read=bis.read(data);
				pw.println("HTTP/1.0 200 Okay"); //先返回状态码
				pw.println();
				pw.flush();
				bos.flush();
				while(read!=-1){
					bos.write(data,0,read);
					read=bis.read(data);
				}
				bos.flush();
			}catch(Exception ex){
				pw.flush();
				bos.flush();
			}
		}

		//返回文件夹下面的所有资源列表
		protected void sendDir(BufferedOutputStream bos,PrintWriter pw,File dir,String req) throws Exception{
			try{
				pw.println("HTTP/1.0 200 Okay"); //先返回状态码
				pw.println();
				pw.flush();

				pw.print("<html><head><title>Directory of ");
				pw.print(req);
				pw.print("</title></head><body><h1>Directory of ");
				pw.print(req);
				pw.println("</h1><table border=\"0\">");

				File[] contents=dir.listFiles();

				for(int i=0;i<contents.length;i++){
					pw.print("<tr>");
					pw.print("<td><a href=\"");
					pw.print(req);
					pw.print(contents[i].getName());
					if(contents[i].isDirectory()){
						pw.print("/");
					}
					pw.print("\">");
					if(contents[i].isDirectory()){
						pw.print("Dir -> ");
					}
					pw.print(contents[i].getName());
					pw.print("</a></td>");
					pw.print("</tr>");
				}
				pw.println("</table></body></html>");
				pw.flush();
			}catch(Exception ex){
				pw.flush();
				bos.flush();
			}
		}
		
	}
		//解析命令行传来的参数
		//param1:资源的根目录 param2:监听的端口
		protected void parseParams(String[] args) throws Exception{
			switch(args.length){
				case 1:
				case 0:
					System.err.println("Syntax:<jvm> "+this.getClass().getName()+"docroot port");
					System.exit(0);
				default:
					this.docroot=args[0];
					this.port=Integer.parseInt(args[1]);
					break;
			}
		}

		//实例化http服务器		
		public Webserver(String[] args) throws Exception{
			System.out.println("Check for parameters");
			
			//解析参数
			parseParams(args);

			System.out.println("starting web server....");

			//监听链接
			this.ss=new ServerSocket(this.port);

			System.out.println("ok");

			for(;;){
				Socket accept=ss.accept();
				//响应请求				
				new Handler(accept,docroot).start();
			}
		}

		public static void main(String[] args) throws Exception{
			Webserver demo=new Webserver(args);
		}
}
运行:在某个文件夹下面放置一些html文件以及一些图片,作为根资源文件夹。然后启动Webserver.java,传递2个参数:param1:刚才新建的根资源文件夹的路径;param2:监听的端口号,然后打开浏览器:http://localhost:8080/。

eg:java Webserver.java /home/volador/test/ 8080

过程很简单,可以根据这个去扩展,实现自己的http服务器。

转载于:https://my.oschina.net/volador/blog/93772

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值