您好,欢迎来到花生壳b2b外贸网信息发布平台!
18951535724
  • HTML是一种用来定义网页的文本,会HTML,就可以编写网页;

       2026-09-01 网络整理佚名970
    核心提示:廖雪峰的官方网站 (liaoxuefeng.com) 研究互联网产品和技术,提供原创中文精品教程

    javaweb消息即时推送

    资深软件开发工程师,业余马拉松选手。

    今天我们访问网站,使用App时,都是基于Web这种Browser/Server模式,简称BS架构,它的特点是,客户端只需要浏览器,应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器,获取Web页面,并把Web页面展示给用户即可。

    Web页面具有极强的交互性。由于Web页面是用HTML编写的,而HTML具备超强的表现力,并且,服务器端升级后,客户端无需任何部署就可以使用到新的版本,因此,BS架构升级非常容易。

    HTTP协议

    在Web应用中,浏览器请求一个URL,服务器就把生成的HTML网页发送给浏览器,而浏览器和服务器之间的传输协议是HTTP,所以:

    HTTP协议是一个基于TCP协议之上的请求-响应协议,它非常简单,我们先使用Chrome浏览器查看新浪首页,然后选择View - Developer - Inspect Elements就可以看到HTML:

    javaweb消息即时推送

    切换到Network,重新加载页面,可以看到浏览器发出的每一个请求和响应:

    javaweb消息即时推送

    对于Browser来说,请求页面的流程如下:

    与服务器建立TCP连接;发送HTTP请求;收取HTTP响应,然后把网页在浏览器中显示出来。

    浏览器发送的HTTP请求如下:

    GET / HTTP/1.1
    Host: www.sina.com.cn
    User-Agent: Mozilla/5.0 xxx
    Accept: */*
    Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8
    

    其中,第一行表示使用GET请求获取路径为/的资源,并使用HTTP/1.1协议,从第二行开始,每行都是以Header: Value形式表示的HTTP头,比较常用的HTTP Header包括:

    服务器的响应如下:

    HTTP/1.1 200 OK
    Content-Type: text/html
    Content-Length: 21932
    Content-Encoding: gzip
    Cache-Control: max-age=300
    ...网页数据...
    

    服务器响应的第一行总是版本号+空格+数字+空格+文本,数字表示响应代码,其中2xx表示成功,3xx表示重定向,4xx表示客户端引发的错误,5xx表示服务器端引发的错误。数字是给程序识别,文本则是给开发者调试使用的。常见的响应代码有:

    从第二行开始,服务器每一行均返回一个HTTP头。服务器经常返回的HTTP Header包括:

    HTTP请求和响应都由HTTP Header和HTTP Body构成,其中HTTP Header每行都以\r\n结束。如果遇到两个连续的\r\n,那么后面就是HTTP Body。浏览器读取HTTP Body,并根据Header信息中指示的Content-Type、Content-Encoding等解压后显示网页、图像或其他内容。

    通常浏览器获取的第一个资源是HTML网页,在网页中,如果嵌入了JavaScript、CSS、图片、视频等其他资源,浏览器会根据资源的URL再次向服务器请求对应的资源。

    关于HTTP协议的详细内容,请参考HTTP权威指南一书,或者Mozilla开发者网站。

    我们在前面介绍的HTTP编程是以客户端的身份去请求服务器资源。现在,我们需要以服务器的身份响应客户端请求,编写服务器程序来处理客户端请求通常就称之为Web开发

    编写HTTP Server

    我们来看一下如何编写HTTP Server。一个HTTP Server本质上是一个TCP服务器,我们先用TCP编程的多线程实现的服务器端框架:

    public class Server {
        public static void main(String[] args) throws IOException {
            ServerSocket ss = new ServerSocket(8080); // 监听指定端口
            System.out.println("server is running...");
            for (;;) {
                Socket sock = ss.accept();
                System.out.println("connected from " + sock.getRemoteSocketAddress());
                Thread t = new Handler(sock);
                t.start();
            }
        }
    }
    class Handler extends Thread {
        Socket sock;
        public Handler(Socket sock) {
            this.sock = sock;
        }
        public void run() {
            try (InputStream input = this.sock.getInputStream()) {
                try (OutputStream output = this.sock.getOutputStream()) {
                    handle(input, output);
                }
            } catch (Exception e) {
            } finally {
                try {
                    this.sock.close();
                } catch (IOException ioe) {
                }
                System.out.println("client disconnected.");
            }
        }
        private void handle(InputStream input, OutputStream output) throws IOException {
            var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
            var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
            // TODO: 处理HTTP请求
        }
    }
    

    只需要在handle()方法中,用Reader读取HTTP请求,用Writer发送HTTP响应,即可实现一个最简单的HTTP服务器。编写代码如下:

    private void handle(InputStream input, OutputStream output) throws IOException {
        System.out.println("Process new http request...");
        var reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
        var writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
        // 读取HTTP请求:
        boolean requestOk = false;
        String first = reader.readLine();
        if (first.startsWith("GET / HTTP/1.")) {
            requestOk = true;
        }
        for (;;) {
            String header = reader.readLine();
            if (header.isEmpty()) { // 读取到空行时, HTTP Header读取完毕
                break;
            }
            System.out.println(header);
        }
        System.out.println(requestOk ? "Response OK" : "Response Error");
        if (!requestOk) {
            // 发送错误响应:
            writer.write("HTTP/1.0 404 Not Found\r\n");
            writer.write("Content-Length: 0\r\n");
            writer.write("\r\n");
            writer.flush();
        } else {
            // 发送成功响应:
            String data = "

    Hello, world!

    "
    ; int length = data.getBytes(StandardCharsets.UTF_8).length; writer.write("HTTP/1.0 200 OK\r\n"); writer.write("Connection: close\r\n"); writer.write("Content-Type: text/html\r\n"); writer.write("Content-Length: " + length + "\r\n"); writer.write("\r\n"); // 空行标识Header和Body的分隔 writer.write(data); writer.flush(); } }

    这里的核心代码是,先读取HTTP请求,这里我们只处理GET /的请求。当读取到空行时,表示已读到连续两个\r\n,说明请求结束,可以发送响应。发送响应的时候,首先发送响应代码HTTP/1.0 200 OK表示一个成功的200响应,使用HTTP/1.0协议,然后,依次发送Header,发送完Header后,再发送一个空行标识Header结束,紧接着发送HTTP Body,在浏览器输入http://local.liaoxuefeng.com:8080/就可以看到响应页面:

    javaweb消息即时推送

    HTTP目前有多个版本,1.0是早期版本,浏览器每次建立TCP连接后,只发送一个HTTP请求并接收一个HTTP响应,然后就关闭TCP连接。由于创建TCP连接本身就需要消耗一定的时间,因此,HTTP 1.1允许浏览器和服务器在同一个TCP连接上反复发送、接收多个HTTP请求和响应,这样就大大提高了传输效率。

    我们注意到HTTP协议是一个请求-响应协议,它总是发送一个请求,然后接收一个响应。能不能一次性发送多个请求,然后再接收多个响应呢?HTTP 2.0可以支持浏览器同时发出多个请求,但每个请求需要唯一标识,服务器可以不按请求的顺序返回多个响应,由浏览器自己把收到的响应和请求对应起来。可见,HTTP 2.0进一步提高了传输效率,因为浏览器发出一个请求后,不必等待响应,就可以继续发下一个请求。

    HTTP 3.0为了进一步提高速度,将抛弃TCP协议,改为使用无需创建连接的UDP协议,目前HTTP 3.0仍然处于实验阶段。

    练习

    编写一个简单的HTTP服务器。

    下载练习

    小结

    使用B/S架构时,总是通过HTTP协议实现通信;

    Web开发通常是指开发服务器端的Web应用程序。

     
    举报收藏 0打赏 0评论 0
    更多>相关评论
    暂时没有评论,来说点什么吧
    更多>同类百科知识
    推荐图文
    推荐百科知识