zoukankan      html  css  js  c++  java
  • 一个简单的web服务器例子

    一个简单的web容器小例子,功能十分简单,只能访问静态资源,对于新手来说还是有一定的意义。主要分三个类

    1、server类:主要功能开启socketServer,阻塞server,接收socket访问,解析request,创建request,作出响应

    public class TestServer1 {
        
        private boolean shutdown = false;
        
        // web目录webroot
        public static final String WEB_ROOT = System.getProperty("user.dir") 
                + File.separator +  "WebRoot";
        
        public static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
        
        public static void main(String[] args) {
            TestServer1 server = new TestServer1();
            server.await();
        }
        
        public void await() {
            
            // 第一步、创建出serverSocket监听本机8080端口
            ServerSocket server = null;
            int port = 8080;
            try {
                server = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
            } catch (Exception e) {
                e.printStackTrace();
            } 
            
            // 第二步、轮询阻塞住socketServer
            while(!shutdown) {
                Socket socket = null;
                InputStream input = null;
                OutputStream output = null;
                
                try {
                    socket = server.accept();
                    input = socket.getInputStream();
                    output = socket.getOutputStream();
                    
                    // 第三步、创建出request,解析request请求
                    Request req = new Request(input);
                    req.parseRequest();
                    
                    // 第四步、创建response
                    Response response = new Response(output);
                    response.setRequest(req);
                    
                    // 第五步、发送简单静态资源,关闭socket结束本次会话
                    response.sendStaticRes();
                    socket.close();
                    
                    // 关闭指令
                    shutdown = req.getUri().equals(SHUTDOWN_COMMAND);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
        
    }

    当然了上面的是最简单的实现,也不能实现多线程,实际上的web容器肯定会创建一个线程池来接收请求

    2、request 主要的工作解析input流,封装成request

    class Request {
        
        private InputStream input;
        
        private String uri;
        
        public Request(InputStream input) {
            this.input = input;
        }
        
        
        /**
         * 解析request请求内容
         * GET /index.html HTTP/1.1
         *    Accept: text/html, application/xhtml+xml, *//*
         *    Accept-Language: zh-CN
         *    User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; MALCJS; rv:11.0) like Gecko
         *    Accept-Encoding: gzip, deflate
         *    Host: localhost:8080
         *    DNT: 1
         *    Connection: Keep-Alive
    * Cookie: 这个地方应该如果有cookie,如果有session还有jsessionId的
    */ public void parseRequest() {
         // 为什么只获取2048个字符,这是因为request请求内容的长度,出于安全或者其他方面的考虑,在浏览器端和服务器端都会做这么一个限制。  StringBuffer buffer
    = new StringBuffer(2048); byte[] bytes = new byte[2048]; int i; try { i = input.read(bytes); } catch (IOException e) { e.printStackTrace(); i=-1; } for(int k=0; k<i; k++) { buffer.append((char)bytes[k]); } System.out.println(buffer.toString()); uri = parseUri(buffer.toString()); } /** * GET /index.html HTTP/1.1 uri的位置 * @param reqStr * @return */ private String parseUri(String reqStr) { int index1, index2; index1 = reqStr.indexOf(' '); if (index1 != -1) { index2 = reqStr.indexOf(' ', index1 + 1); if (index2 > index1) return reqStr.substring(index1 + 1, index2); } return null; } public String getUri() { return uri; } }

    解析成的http请求的具体内容,作为web开发人员应该要熟悉每个字段的意义,这个请求是浏览器本身按照http协议封装的一个请求,能够手写出这个请求当然更好。

    3、response 通过request的uri找到对应的资源对请求作出响应,实际的情况肯定是有静态和动态资源例如servletfilter等等,但是这里只是做了简单的静态的处理了

    class Response {
        
        private OutputStream output;
        
        private Request request;
        
        public Response(OutputStream output) {
            this.output = output;
        }
        
        public void setRequest(Request req) {
            this.request = req;
        }
        
        /**
         * 简单处理静态资源
         * @throws IOException
         */
        public void sendStaticRes() throws IOException {
            
            FileInputStream fis = null;
            try {
                File staticFile = new File(TestServer1.WEB_ROOT, request.getUri());
                if(staticFile.exists()) {
                    fis = new FileInputStream(staticFile);
                    int i = 0;
                    byte[] buf = new byte[1024];
              // 流的对拷 i
    = fis.read(buf, 0, 1024); while(i!=-1) { output.write(buf, 0, i); i = fis.read(buf, 0, 1024); } } else { // file not found 404 String errorMessage = "HTTP/1.1 404 File Not Found " + "Content-Type: text/html " + "Content-Length: 23 " + " " + "<h1>File Not Found</h1>"; output.write(errorMessage.getBytes()); } } catch (Exception e) { e.printStackTrace(); } finally{ if(fis!=null) fis.close(); fis = null; } } }

    同样响应内容你也应该要熟悉哪些组成部分

    HTTP/1.1 200 OK  //响应行
    Date: Sat, 31 Dec 2005 23:59:59 GMT
    Content-Type: text/html;charset=ISO-8859-1
    Content-Length: 122
    
    <html>
    <head>
    <title>Test</title>
    </head>
    <body>
    This my page
    </body>
    </html>

    至此一个简单的web容器就写好了,能够访问webRoot目录下的静态资源。

    可以通过浏览器访问,也可以通过telnet端进行访问。在cmd命令行下telnet localhost 8080,就会连接上socketServer,然后就会等待输入,自然我们输入对应的请求报文,回车响应内容就出现了。

    以上原创文章出自老罗家的树博客地址:http://www.cnblogs.com/TimBing/ 

  • 相关阅读:
    第一章 概述
    Angular-----代码风格指南!!!(很重要)
    Angular中innerHTML标签的样式不起作用详解
    maven入门
    vue解惑之v-on(事件监听指令)
    vue解惑之slot(插槽)
    js中关于constructor与prototype的理解
    Angular--AOT和JIT两种编译方式带来的改变
    ArcGIS API for JavaScript小白入门
    ionic项目使用Google FCM插件和Google maps插件打包android报错冲突问题
  • 原文地址:https://www.cnblogs.com/TimBing/p/4382423.html
Copyright © 2011-2022 走看看