微信号:newbiefly1

介绍:专注于分享全面免费的IT开发视频资料,目前整理的包含大数据;IOS;Android;JNI技术;游戏开发;c/c++;数据结构;黑客技术;javaweb;.net;html5;javascript;div+css等欢迎相互学习共同成长.

自己动手实现静态资源服务器

2018-06-13 17:30 菜鸟要飞

作者:孤独烟
原文:https://www.cnblogs.com/rjzheng/p/8750265.html

引言

本文利用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\n");
                   sb.append("Content-Type: text/html; charset=UTF-8\n");
                   sb.append("\n");
                   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
显示如下图所示

控制台输出如下图所示

====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)步骤一

先看第一部分代码优化,如下图所示

红框的部分,我们可以理解为对请求信息对处理,因此我们模仿Tomcat构造一个HttpRequst来处理这一段逻辑。

另外,我们需要对静态资源进行响应,因此我们需要获取输入内容的静态资源地址,即以下部分的内容。

获取以上红框请求地址内容的代码如下

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)步骤二

接下来是第二部分的代码优化,如下图所示

以上红框部分主要是对输出信息进行响应,我们模仿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\n");
       sb.append("Content-Type: text/html; charset=UTF-8\n");
       sb.append("\n");
       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图片拷贝至你的根目录下
静态资源在你的项目中的结构如下图所示

现在上我们的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
效果如下

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

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

继续启动测试,效果如下

已经能够正常显示

总结

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


 
菜鸟要飞 更多文章 一次惊险的跳槽面试经历(阿里\/美团\/头条\/网易\/有赞...) 周一上班伐开心?分享三个超实用的爬虫案例高兴一下 当年的你不像现在只会写代码,如此牛逼! 温馨提示: 高考信号屏蔽到底是个什么鬼? 本科应届 28万年薪:决定你薪资高低的,是这1条潜规则
猜您喜欢 为什么说死亡是企业的宿命? Jboss项目下载与远程调试方法 神级程序员教你用Python实现简单的导弹自动追踪!此乃装逼神技! 在武汉,谁比我强? 一期班创平均薪资7471元!