自己手写一个简单的tomcat服务器

Tomcat服务器本质上就是一个 Server的程序,所以这里我们先写一个Server的程序和一个Socket程序,然后在对其进行改装

Server服务端的程序见下文所示

public class Server {


	/*
	 Tomcat其实就是一个socket编程
	 	下面的流程中 有两个流程,
	 	
	 	第一个流程是 客户端请求浏览器的流程
	 	第二个业务流程是 服务器给客户端返回数据的业务流程
	 	
	 	
	 	两个业务类型不同,在这里可以抽取两个业务类  来分别抽取 两个不同的业务类
	 	
	 	抽取HttpRequest 和 HttpResponse 两种业务
	 	
	 */
	public static void main(String[] args) {
		
		//发送信息的电报机
		ServerSocket serverSocket = null;
		Socket client = null;
		try{
			serverSocket = new ServerSocket( 8888 );
			System.out.println("服务器初始化完毕,初始化的端口是 8888");
			//这里在不断的接收客户端请求
			while(true){
				//服务端接收客户端的Socket连接过来
				client = serverSocket.accept();
				//对客户端端里面的请求信息进行处理
				InputStream in = client.getInputStream();	
				//定义一个读取缓冲流,主要是在InputStream流当中读取这些字节
				byte[] buff = new byte[1024];
				int len = in.read(buff);
				if(len>0){
					String msg = new String(buff,0,len);
					System.out.println("客户端请求信息!"+"============"+msg+"============");
					OutputStream os = client.getOutputStream();
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					
					//构建一个响应头信息 200 OK
					StringBuffer sb = new StringBuffer();
					//响应头信息
					
					sb.append("HTTP/1.1 200 OK\n");
					sb.append("Content-Type: text/html;charset=UTF-8\n");
					sb.append("cahce-control:max-age-0");
					sb.append("Upgrade-Insecure-Requests: 1");
					sb.append("User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");
					sb.append("Accept-Encoding:gzip, deflate, br");
					sb.append("Accept-Language:zh-CN,zh;q=0.9");
					sb.append("\r\n");
					
					
					
					
				//响应正文
					String html = "欢迎各位同学  当前时间:" +
						"" +
						format.format(new Date()) +
						"
服务器回复: 大家今天有收货吗 " + "
服务器回复:大家今天有收获吗" + ""; //把响应头和正文都连接在了一起 sb.append(html); //响应业务, os.write(sb.toString().getBytes()); os.flush(); os.close(); } } }catch(Exception e){ } }


接下来是一个 客户端client的程序
public class Client {
	
	public static void main(String[] args) {
		
		 try {
	         Socket s = new Socket("127.0.0.1",8888);
	         
	         //构建IO
	         InputStream is = s.getInputStream();
	         OutputStream os = s.getOutputStream();
	         
	         BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
	         //向服务器端发送一条消息
	         bw.write("测试客户端和服务器通信,服务器接收到消息返回到客户端\n");
	         bw.flush();
	         
	         //读取服务器返回的消息
	         /*
	         
	         BufferedReader br = new BufferedReader(new InputStreamReader(is) );
	         
	         String line = br.readLine();
	         
	         System.out.println( line );
	         */
	         
	         
	         StringBuffer sb = new StringBuffer();
	         int len = 0;
	         byte[] buff = new byte[1024];
	         while( (len = is.read(buff) )!=-1 ){
	        	 
	        	 sb.append( new String(buff,0,len) );
	        	 
	         }
	         
	         System.out.println(  sb.toString()  );
	         
	         
		 } catch (UnknownHostException e) {
	         e.printStackTrace();
	      } catch (IOException e) {
	         e.printStackTrace();
	      }
		
	}
	
}
启动服务端然后便可以看到客户端与服务器端互相通信已经畅通

然后考虑到tomcat中在实现其功能的时候需要将其业务拆分,拆分成  处理请求的一部分和返回响应的一部分,所以这里对代码进行改进,新建一个Server2.java,项目的目录结构如下图所示:

自己手写一个简单的tomcat服务器_第1张图片

Server2.java代码

package com.zwz;


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class Server2 {
	
	static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	
   public static void main(String[] args) {
      try {
     
    	  ServerSocket ss = new ServerSocket(8888);
	      System.out.println("启动服务器....8888端口");
    	  
    	  while(true){
	    	 
	         Socket s = ss.accept();
	         System.out.println("客户端:"+s.getInetAddress().getLocalHost()+"已连接到服务器");
	         
	         BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
	        
	         HttpRequest request = new HttpRequest( s.getInputStream() );
	         
	         String requesturi = request.getUri();
	         
	         System.out.println("请求路径是:"+requesturi);
	         
	         HttpResponse response = new HttpResponse(s.getOutputStream());
	       
	         
	         //if(isStatic(requesturi)){
	         	response.writeFile(requesturi);
	         //}
	         
	         s.close();
    	  }
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
   
   
   //静态资源的重复获取需要通过过滤
   public static boolean isStatic( String uri ){
	   
	   boolean isStatic = false;
	   
	   String []suffixs = {"html","css","js","jpg","png","gif","bmp"};

	   for( String suffix : suffixs){
		   if(uri.endsWith("."+suffix)){
			   isStatic = true;
			   break;
		   }
	   }
	   return isStatic;
   }
   
}


HttpReuqest.java代码:

package com.zwz;

import java.io.IOException;
import java.io.InputStream;


public class HttpRequest {
	
	private String uri;

	public String getUri() {
		return uri;
	}

	public void setUri(String uri) {
		this.uri = uri;
	}
	
	
	public HttpRequest(InputStream in)  throws IOException{
		resolverRequest(in);
	}

	private void resolverRequest(InputStream in) throws IOException {
		
		//1.读取 客户端请求过来的数据,解析出来uri
		byte[] buff = new byte[1024];
		int len = in.read(buff);
		
		if( len>0 ){
			String msg = new String(buff,0,len);
			
			System.out.println("客户端请求信息");
			
			System.out.println("客户端请求过来的数据是:" + msg );
			
			this.uri = msg.substring( 4,msg.indexOf("HTTP/1.1")  );
			
			
			
		}else{
			
			System.out.println("bad request!");
			
		}
		
	}
	
	
	public static void main(String[] args) {
		
	}
	
	
	
}
HttpResponse.java代码

package com.zwz;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;


public class HttpResponse {

	private OutputStream out = null;

	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	
	
	public HttpResponse(OutputStream out) {
		super();
		this.out = out;
	}
	
	
	//这个方法的作用是把请求的地址传递进来,服务器这个时候向客户端回写响应的文件数据等
	public void writeFile( String path ) throws IOException{
		
    		
			String basepath = new File("").getCanonicalPath();
			
			FileInputStream fis = new FileInputStream( basepath +"/"+ path);
			byte[] buff = new byte[1024];
			int len = 0;
			StringBuffer sb = new StringBuffer();
			//拼凑响应头信息
			sb.append("HTTP/1.1 200 OK\n");
			//sb.append("Content-Type: text/html;charset=UTF-8\n");
			sb.append("\r\n");
			
			
			//响应业务,
			out.write(sb.toString().getBytes());
        
			while((len=fis.read(buff))!=-1){
				out.write(buff,0,len);
			}
	
		fis.close();		
        out.flush();
        out.close();
    
	}
	
	
	
}

代码结束之后开始运行下整个项目工程,首先我们需要拷贝一个前端羡慕到eclipse当中,放置在项目的根目录:

自己手写一个简单的tomcat服务器_第2张图片

这个时候运行 server2.java这个文件

在浏览器地址蓝输入  localhost:8888/test/demo.html,显示页面如下

自己手写一个简单的tomcat服务器_第3张图片

ok,到这里大功告成,已经手写实现了一个简单的tomcat  服务






你可能感兴趣的:(java)