zoukankan      html  css  js  c++  java
  • 【原创】自己动手实现静态资源服务器

    引言

    本文利用java自带的socket编程实现了一个简单的静态资源服务器,可以响应静态资源。本文一共有两个版本的源码。第一个版本名为Server_v1,该版本实现了一个简单的socket的服务器,帮助读者回忆socket编程。第二个版本名为Server_v2,该版本是对第一版的改良,给出了改良思路,做出了必要的封装,让其能够响应css、html、jpg等静态资源。

    正文

    版本一

    该版本实现一个简单的socket服务器,针对浏览器的请求,能够返回相应的页面。
    其源码如下:

    package mytomcat_v1;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
    
    /**
     * 
     * @author zhengrongjun
     * @version v1.0
     */
    public class Server_V1 {
    
    	public static void main(String[] args) {
    		ServerSocket serverSocket = null;
    		Socket client = null;
    		try {
    			serverSocket = new ServerSocket(9999);
    			// 不断接收客户连接
    			while (true) {
    				// 服务器阻塞等待客户端socket连接过来
    				client = serverSocket.accept();
    				// 对客户端里面端请求信息进行处理
    				InputStream in = client.getInputStream();
    				// 定义一个读取缓冲池 主要是在inputstram流中读取字节
    				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 out = client.getOutputStream();
    					//构建响应信息
    					StringBuffer sb = new StringBuffer();
    					sb.append("HTTP/1.1 200 OK
    ");
    					sb.append("Content-Type: text/html; charset=UTF-8
    ");
    					sb.append("
    ");
    					String html="<html><head><title>卖烧饼咯</title></head></html><body>小曲经常在"
    							   +"<font size='14' color='red'>"
    							   +new Date()
    							   +"</font>"
    							   +"<br/>卖烧饼</body></html>";
    					sb.append(html);
    					out.write(sb.toString().getBytes());
    					out.flush();
    					out.close();
    				}
    			}
    		} catch (Exception e) {
    
    		}
    
    	}
    
    }
    
    

    执行效果如下图所示,打开chrome浏览器,在导航栏输入

    http://localhost:9999/docs/index.html
    

    显示如下图所示
    image

    控制台输出如下图所示

    ====GET /docs/index.html HTTP/1.1
    Host: localhost:9999
    Connection: keep-alive
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9
    ======
    

    版本二

    该版本在版本一的基础上进行优化,使其能够有效的响应静态资源

    (1)步骤一

    先看第一部分代码优化,如下图所示
    image
    红框的部分,我们可以理解为对请求信息对处理,因此我们模仿Tomcat构造一个HttpRequst来处理这一段逻辑。

    另外,我们需要对静态资源进行响应,因此我们需要获取输入内容的静态资源地址,即以下部分的内容。
    image
    获取以上红框请求地址内容的代码如下

    uri = msg.substring(msg.indexOf("/"),msg.indexOf("HTTP/1.1") - 1);
    

    综上所述,我们有HttpRequest类如下所示

    package mytomcat_v2;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * 对客户端进行处理对业务类
     * 
     * @author zhengrongjun
     *
     */
    public class HttpRequest {
    	private String uri;
    
    	public String getUri() {
    		return uri;
    	}
    
    	public HttpRequest(InputStream in) throws IOException {
    		// 对我们对请求字节流进行解析
    		resolverRequest(in);
    
    	}
    
    	private void resolverRequest(InputStream in) throws IOException {
    		// TODO Auto-generated method stub
    		byte[] buff = new byte[1024];
    		int len = in.read(buff);
    		if (len > 0) {
    			String msg = new String(buff, 0, len);
    			System.out.println("====" + msg + "======");
    			// 解析出来 uri
    			uri = msg.substring(msg.indexOf("/"), msg.indexOf("HTTP/1.1") - 1);
    		} else {
    			System.out.println("bad Request!");
    		}
    	}
    
    }
    
    

    (2)步骤二

    接下来是第二部分的代码优化,如下图所示
    image
    以上红框部分主要是对输出信息进行响应,我们模仿tomcat构造一个HttpResponse对象封装该部分逻辑。
    另外,我们获取用户请求的资源文件路径,根据该路径找到相应静态文件。将该文件写入文件流,输出。
    因此,我们有HttpResponse对象如下所示

    package mytomcat_v2;
    /**
     * 封装http响应信息
     * @author zhengrongjun
     *
     */
    
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    
    public class HttpResponse {
    
    	private OutputStream os = null;
    
    	public HttpResponse(OutputStream os) {
    		this.os = os;
    	}
    
    	public void writerFile(String path) throws IOException {
    		FileInputStream fileInputStream = new FileInputStream(path);
    		byte[] buff = new byte[1024];
    		int len = 0;
    		// 构建响应信息
    		StringBuffer sb = new StringBuffer();
    
    		sb.append("HTTP/1.1 200 OK
    ");
    		sb.append("Content-Type: text/html; charset=UTF-8
    ");
    		sb.append("
    ");
    		os.write(sb.toString().getBytes());
    		while ((len = fileInputStream.read(buff)) != -1) {
    			os.write(buff, 0, len);
    		}
    		fileInputStream.close();
    		os.flush();
    		os.close();
    	}
    }
    
    

    (3)步骤三

    接下来我们构建测试类,构建之前我们先去找一些静态资源文件。作者直接去apache的官网下把tomcat给下了下来,然后去如下目录拷贝静态资源文件

    apache-tomcat-8.5.28/webapps/docs
    

    将整个docs 文件夹拷贝至你的项目的根目录下

    apache-tomcat-8.5.28/webapps/ROOT/favicon.ico
    

    将favicon.ico图片拷贝至你的根目录下
    静态资源在你的项目中的结构如下图所示
    image

    现在上我们的Server_V2的代码

    package mytomcat_v2;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
    
    /**
     * 
     * @author zhengrongjun
     * @version v2.0
     */
    public class Server_V2 {
    
    	public static void main(String[] args) {
    		ServerSocket serverSocket = null;
    		Socket client = null;
    		try {
    			serverSocket = new ServerSocket(9999);
    			// 不断接收客户连接
    			while (true) {
    				// 服务器阻塞等待客户端socket连接过来
    				client = serverSocket.accept();
    				// =========请求类处理=======
    				InputStream in = client.getInputStream();
    				HttpRequest request = new HttpRequest(in);
    				String requestUri = request.getUri();
    				// =========响应类处理=======
    				OutputStream os = client.getOutputStream();
    				HttpResponse response = new HttpResponse(os);
    				//请求格式是/html/login.html这种,需要把开头的/删除
    				response.writerFile(requestUri.substring(1));
    				client.close();
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    
    	}
    
    }
    
    

    测试结果如下:
    在浏览器输入

    http://localhost:9999/docs/ssl-howto.html
    

    效果如下
    image
    你会惊奇的发现样式并不能识别,因此我们对响应头的部分逻辑进行修改

    sb.append("HTTP/1.1 200 OK
    ");
    sb.append("Content-Type: text/html; charset=UTF-8
    ");
    sb.append("
    ");
    

    部分修改为

    if(path.endsWith("css")) {
    			sb.append("HTTP/1.1 200 OK
    ");
    			sb.append("Content-Type: text/css; charset=UTF-8
    ");
    			sb.append("
    ");
    		}else {
    			sb.append("HTTP/1.1 200 OK
    ");
    			sb.append("Content-Type: text/html; charset=UTF-8
    ");
    			sb.append("
    ");
    		}
    
    

    继续启动测试,效果如下
    image
    已经能够正常显示

    总结

    本文给出了两个版本的静态资源的服务器源码,希望读者能够有所收获。

  • 相关阅读:
    php笔记--php安装
    IEDA-Git的应用
    php类型
    3.比较与逻辑运算
    2.阶乘
    1.双分支
    013_request对象包含的内容以及获取
    011_jsp引入JSTL后实现jsp的解耦
    010_jsp引入JSTL
    ORACLE1.28 面试题
  • 原文地址:https://www.cnblogs.com/rjzheng/p/8886298.html
Copyright © 2011-2022 走看看