• 手写一个Web服务器,极简版Tomcat


    网络传输是通过遵守HTTP协议的数据格式来传输的。

    HTTP协议是由标准化组织W3C(World Wide Web Consortium,万维网联盟)和IETF(Internet Engineering Task Force,国际互联网工程任务组)推动和制定的,最后形成RFC文档 [RFC1945](HTTP/1.0)和RFC2616[HTTP/1.1]

    可以响应HTTP请求的程序就是Web Server,实现方法并没有统一规范,可以说HTTP协议就是Web Server和网络传输数据之间的接口规范。以后我们会看到,Web Server和处理程序之间的规范是CGI。

    一些常见的Web Server有Apache、Nginx、Microsoft IIS、Google GWS。

    我们这里手写一个Web Server。

    首先我们需要接收网络的请求,根据OSI七层模型,网络的实现是分层的。Web Server属于应用层,要调用下一层(传输层,TCP/IP)的接口,来得到对方发来的网络请求,这个接口就叫做Socket。《计算机网络:自顶向下方法》中写到:“Socket是同一台主机内应用层与传输层之间的接口。因为Socket是建立网络应用程序的可编程接口,所以Socket也被称为应用程序和网络之间的API”。

    一、最简单的Web Server

    要编写一个Web Server,我们调用系统Socket接口,监听8180端口上收到的网络数据,打印到控制台,并给出一个符合http标准的响应,代码如下:

    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.Date;
     
    public class Server {
        public static void main(String[] args) {
            Server server = new Server();
            server.start();
        }
     
        public void start() {
            try {
                ServerSocket serverSocket = new ServerSocket(8180); // 调用系统socket接口,监听某端口的socket请求
                Socket httpInputSocket = serverSocket.accept(); // 在这里,程序线程等待socket输入
                this.printHttpRequest(httpInputSocket);
                this.responseHttpRequest(httpInputSocket);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        /**
         * 打印来自外部的http请求
         *
         * @param httpInputSocket
         */
        private void printHttpRequest(Socket httpInputSocket) {
            try {
                // 调用系统IO,打印请求
                BufferedReader br = new BufferedReader(new InputStreamReader(httpInputSocket.getInputStream()));
                StringBuilder receivedHttp = new StringBuilder();
                String line = null;
                while ( !"".equals(line = br.readLine())) {
                    receivedHttp.append(line);
                    receivedHttp.append(System.getProperty("line.searator", "
    "));
                }
                System.out.println(receivedHttp.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
     
        /**
         * 返回页面供请求方显示
         *
         * @param httpInputSocket
         */
        private void responseHttpRequest(Socket httpInputSocket) {
     
            // 创建响应体
            StringBuilder contextText = new StringBuilder();
            contextText.append(
                    "<html>" +
                            "<head>" +
                            "<title>Build A Web Server</title>" +
                            "</head>" +
                            "<body>Hello World, This is my page</body>" +
                            "</html>");
     
            // 创建响应头
            StringBuilder headText = new StringBuilder();
            headText.append("HTTP/1.1").append(" ").append("200").append(" ").append("OK").append("
    ");
            headText.append("Server:myServer").append(" ").append("0.0.1v").append(" ");
            headText.append("Date:Sat,"+" ").append(new Date()).append("
    ");
            headText.append("Content-Type:text/html;charset=UTF-8").append("
    ");
            headText.append("Content-Length:").append(contextText.toString().getBytes().length).append("
    ");
     
            // http response
            StringBuilder responseText = new StringBuilder();
            responseText.append(headText).append("
    ").append(contextText);
            System.out.println(responseText);
     
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new OutputStreamWriter(httpInputSocket.getOutputStream()));
                bw.write(responseText.toString());
                bw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

    至此,一个100行不到的Web Server就写好了,运行一下,在浏览器里访问:http://localhost:8180/,可以看到结果:

    程序控制台也正确打印:

    这个Web Server会对请求到8180端口的所有请求都返回同样的页面,比如我们访问http://localhost:8180/really?foo=123,结果也是一样的:

    从这个例子可以看出,通过HTTP请求进行访问,可以不用创建socket客户端。 注意printHttpRequest和responseHttpRequest都要调用才能显示效果,就是说先执行socket 输入流的读取,然后再执行socket输出流输出

  • 相关阅读:
    js 获取asp.net TextBox值
    项目笔记一
    如何取GridView中隐藏列的值
    使用bablepolyfill
    border: 0.5px
    选择查询固定位置的数据
    SQL用户数据库权限设置
    Java.1 HelloWorld的分析
    Java.2 面向对象
    【drupal实践】windows下drupal7.22develop版本安装
  • 原文地址:https://www.cnblogs.com/lipengsheng-javaweb/p/12973429.html
Copyright © 2020-2023  润新知