创建一个简单的web服务器

来源:互联网 发布:淘宝旺旺客服电话 编辑:程序博客网 时间:2024/05/19 23:15

Web服务器也称为超文本传输协议(HTTP)服务器,因为它使用HTTP来跟客户端进行通信的。既然说到通信那就离不了Java里的两个重要的类java.net.Socket和java.net.ServerSocket。这里浏览器一方可以认为是一个客户端,接收HTTP请求的一方可以认为是服务端。在这之前我们先说一下HTTP协议。

HTTP协议允许web服务器和浏览器通过网络来进行发送和接收数据。它是一种请求和响应协议。客户端发送一个请求,服务端响应这个请求。HTTP请求由三部分组成,分别是:请求行、消息报头(请求头)、请求正文(一般是POST请求)。注意:请求头和请求正文中间有一个空行。一个请求行以一个方法开头,一个空格隔开,后面跟着请求的URI和协议的版本。格式如下Method Request-URI HTTP-Version CRLF。其中Method表示请求方法,Request-URI是一个统一资源标识符,HTTP-Version表示请求的HTTP协议版本,CRLF表示回车和换行(除了作为结尾的CRLF之外,不允许出现单独的CR或LF字符)HTTP响应也是由三个部分组成,分别是:状态行、消息报头(响应头)、响应正文。响应头和响应正文中间有一个空行。状态行的格式如下:HTTP-Version Status-Code Reason-Phrase CRLF。其中,HTTP-Version表示服务器HTTP协议的版本,Status-Code表示服务器发回的响应状态码,Reason-phrase表示状态代码的文本描述。说了这么多可能你看的还是有点晕,通过下面这张图你应该能看得更清楚一点:


OK,我们上面说了浏览器可以当做是一个客户端,那么我们只需要写一个服务端就行了。下面的代码只是简单的模拟了请求静态资源和处理一个简单的Servlet。

服务端代码如下:

package com.zkn.imitate.tomcat.secondchapter.first;import com.zkn.imitate.tomcat.secondchapter.Request;import com.zkn.imitate.tomcat.secondchapter.Response;import com.zkn.imitate.tomcat.secondchapter.StaticResourceProcessor;import com.zkn.imitate.tomcat.utils.Constants;import com.zkn.imitate.tomcat.utils.StringUtil;import java.io.IOException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;/** * Created by wb-zhangkenan on 2016/12/29. */public class HttpServer {    public static void main(String[] args){        await();    }    private static void await() {        ServerSocket serverSocket = null;        try {            boolean shutDown = false;            //创建一个服务端            serverSocket = new ServerSocket(8004,1, InetAddress.getByName("127.0.0.1"));            while (!shutDown){                //接收客户端请求                Socket socket = serverSocket.accept();                Request request = new Request(socket.getInputStream());                request.parseRequest();//解析请求信息                Response response = new Response(socket.getOutputStream());                String uri = request.getUri();                if(uri !=null && uri.startsWith("/favicon.ico")){                }else if(!StringUtil.isEmpty(uri) && uri.startsWith("/static/")){                    StaticResourceProcessor resouce = new StaticResourceProcessor();                    resouce.process(request,response);//处理静态资源                }else{                    ServletProcessor servletProcessor = new ServletProcessor();                    servletProcessor.process(request,response);//处理Servlet                }                socket.close();                shutDown = Constants.SHUT_DOWN.equals(request.getUri());            }        } catch (IOException e) {            e.printStackTrace();        }    }}
模拟的Request主要代码如下:

public class Request implements ServletRequest {    /**     * 输入流     */    private InputStream inputStream;    /**     * uri     */    private String uri;    public Request(InputStream inputStream) {        this.inputStream = inputStream;    }    public void parseRequest(){        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));        StringBuffer sb = new StringBuffer();        String str = null;        try {            while((str = br.readLine()) != null){                if("".equals(str))                    break;                sb.append(str).append("\n");            }            System.out.println(sb.toString());            uri = StringUtil.parserUri(sb.toString()," ");        } catch (IOException e) {            e.printStackTrace();        }    }
模拟的Response主要代码如下:

public class Response implements ServletResponse {    /**     * 输出流     */    private OutputStream outputStream;    /**     * 字符输出流     */    private PrintWriter printWriter;    public Response(OutputStream outputStream) {        this.outputStream = outputStream;    }    public void sendStaticResource(String path) {        FileInputStream fis = null;        try {            File file = new File(Constants.WEB_PATH, path);            if (file.exists() && !file.isDirectory()) {                if (file.canRead()) {                    fis = new FileInputStream(file);                    int flag = 0;                    byte[] bytes = new byte[1024];                    while ((flag = fis.read(bytes)) != -1){                        outputStream.write(bytes);                    }                }            }else{                PrintWriter printWriter = getWriter();                //这里用PrintWriter字符输出流,设置自动刷新                printWriter.write("HTTP/1.1 404 File Not Found \r\n");                printWriter.write("Content-Type: text/html\r\n");                printWriter.write("Content-Length: 23\r\n");                printWriter.write("\r\n");                printWriter.write("<h1>File Not Found</h1>");                printWriter.close();            }        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }finally {            if(fis != null)                try {                    fis.close();                } catch (IOException e) {                    e.printStackTrace();                }        }    }
静态资源处理类:

public class StaticResourceProcessor {    public void process(Request request,Response response){        response.sendStaticResource(request.getUri());    }}
Servlet处理类如下:

public class FirstServlet implements Servlet{    public void init(ServletConfig servletConfig) throws ServletException {    }    public ServletConfig getServletConfig() {        return null;    }    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {        PrintWriter out = servletResponse.getWriter();        out.println("Hello. Roses are red.");    }    public String getServletInfo() {        return null;    }    public void destroy() {    }}

ServletProcessor的代码如下:

package com.zkn.imitate.tomcat.secondchapter.first;import com.zkn.imitate.tomcat.secondchapter.Request;import com.zkn.imitate.tomcat.secondchapter.Response;import com.zkn.imitate.tomcat.utils.Constants;import com.zkn.imitate.tomcat.utils.StringUtil;import javax.servlet.Servlet;import javax.servlet.ServletException;import java.io.File;import java.io.IOException;import java.net.URL;import java.net.URLClassLoader;import java.net.URLStreamHandler;/** * Created by wb-zhangkenan on 2016/12/29. */public class ServletProcessor {    /**     * 处理请求信息     * @param request     * @param response     */    public void process(Request request, Response response){        String str = request.getUri();        String servletName = null;        if(!StringUtil.isEmpty(str) && str.lastIndexOf("/") >= 0){            servletName = str.substring(str.lastIndexOf("/")+1);        }        URLClassLoader classLoader = null;        URL[] url = new URL[1];        URLStreamHandler streamHandler = null;        File classPath = new File(Constants.WEB_ROOT);        try {            //创建仓库            String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString();            url[0] = new URL(null,repository,streamHandler);            classLoader = new URLClassLoader(url);//URL类加载器            Class clazz = classLoader.loadClass(servletName);            Servlet servlet = (Servlet) clazz.newInstance();            servlet.service(request,response);        } catch (IOException e) {            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (ServletException e) {            e.printStackTrace();        }    }}
下面我们看一下请求结果如何:

当我们输入:http://localhost:8004/FirstServlet时,请求结果如下所示:

当我们输入:http://localhost:8004/static/image01.jpg时,请求结果如下所示:


从上面的结果可以看到,我们做的简单的web服务器可以正常工作了。当然了这个只是最简单的web服务器了,以后我会把这个写的完整一些强大一些。完整的代码请从这里下载:https://github.com/zhangconan/ImitateTomCat





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝宝肚子着凉吐怎么办 孩子胃着凉呕吐怎么办 一岁受凉呕吐怎么办 孩子着凉了呕吐怎么办 小孩受凉呕吐腹泻怎么办 宝宝胃受寒呕吐怎么办 一岁半宝宝受寒呕吐怎么办 治小儿反复发烧怎么办 海洋宝宝吃下去怎么办 两岁儿童拉肚子怎么办 14天宝宝拉肚子怎么办 小孩不消化引起发烧怎么办 宝宝胃胀呕吐怎么办 小儿胃胀不消化怎么办 4岁小儿腹胀怎么办 两岁半的宝宝吐怎么办 月子宝宝闹人怎么办 宝宝一周岁拉肚子怎么办 一岁幼儿呕吐怎么办 孩子受凉呕吐拉肚子怎么办 5岁儿童呕吐怎么办 小孩发烧老是吐怎么办 宝宝吃雪糕呕吐怎么办 小孩感冒发烧吐怎么办 宝宝呕吐加发热怎么办 七个月宝拉肚子怎么办 新生儿17天拉稀怎么办 七个半月宝宝拉肚子怎么办 七个月婴儿拉稀怎么办 宝宝不停的拉稀怎么办 猫咪受凉了呕吐怎么办 孩子生理性腹泻怎么办 婴儿肚子受凉了怎么办 小孩说话有点口吃怎么办 3岁宝宝先拉后吐怎么办 1岁宝宝拉肚子怎么办 2岁宝宝结巴怎么办 小孩吐和拉肚子怎么办 头外伤后头晕怎么办 紧张性神经头痛怎么办 小孩吃饱受凉吐怎么办