Http协议的相关概念

发布于:2023-01-09 ⋅ 阅读:(581) ⋅ 点赞:(0)

目录

HTTP协议

HTTP的发展

Web资源

HTTP协议的完整流程

请求

客户端

​编辑

响应

服务器

URI和URL

资源路径

动态资源

URL字符的要求

HTTP请求中的关键信息 

请求方法

演示1:通过

发送POST 请求

演示2:

ajax请求/xhr请求 

执行顺序

非常常见的一道面试题

面试题小结

演示3: 使用ajax发送post+携带请求体的请求

HTTP响应中的关键信息  

重定向

响应头

form表单提交

小结


HTTP协议

Web应用中的基本单位是Web资源。Web资源分布在网络中的任意主机上,所以本机的浏览器要获取这些Web资源,就必须通过一种网络协议——HTTP协议。

HTTP协议是以Web资源为基本单位。
每次请求-响应只能针对一个Web资源进行。

HTTP的发展

HTTP: Hyper(超)Text (文本)Transfer(传输)Protocol(协议)
HTTP协议设计肇始,是为了传输超文本(HTML的前身),随着互联网的发展,HTTP协议传输的不仅仅是超文本了,目前其实任意类型都可以。

围绕着超文本这套类型发展出来的前端三剑客(HTML、CSS、JavaScript)还是其主流;除此之外,其他多媒体资源也是非常常见的:图片、音频、视频等。

HTTP协议是一套应用层协议(一开始专注于业务,但现在HTTP协议本身也成为基础协议之一了),所以HTTP协议必须在一套传输层协议上进行传输。传输层的候选协议:UDP、TCP。
HTTP在1.0、1.1、2.0是基于TCP协议之上进行工作的。(HTTP协议中本身没有设计任何提供可靠性的机制,依赖传输层及以下网络已经提供可靠服务)
HTTP 在3.0之后,开始基于UDP协议上进行了。(HTTP协议内部自己做可靠性工作了)

HTTP协议的客户端,一般称为浏览器,同时又被称为用户代理(User-Agent)等名称,网景浏览器可以说是最早的浏览器了。

Web资源

Web资源:某些内容或者是执行一些动作,以服务的形式体现。购买一本书(书就是 web资源)、发个快递(发快递动作是web资源)。

HTTP协议的完整流程

重点是理解HTTP格式:请求格式和响应格式

请求

客户端

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * 只能进行一次请求-响应的 HTTP 客户端
 */
public class MyHttpClient {
    public static void main(String[] args) throws IOException {
        // 主机       127.0.0.1
        // 端口       8080
        // 资源路径    /hello.html
        try (Socket socket = new Socket("127.0.0.1", 8080)) {
            // 准备 HTTP 请求内容
            // 文本   String
            // 格式:请求行
            String requestLine = "GET /hello.html HTTP/1.0\r\n";

            // 请求头:完全可以没有,但必须一个空行结尾
            // 请求头中共有 1对 key-value
            String requestHeader1 = "Name: xxx\r\n\r\n";
            // 请求头中共有 2对 key-value
            String requestHeader2 = "Name: xxx\r\nAge: 1993\r\n\r\n";
            // 请求头中共有 0 对 key-value
            String requestHeader3 = "\r\n";
            // 请求体,GET 是没有请求体

            // 最终的请求 —— 要发送给服务器的东西
            String request = requestLine + requestHeader3;

            // 发送服务器的过程
            byte[] requestBytes = request.getBytes("ISO-8859-1"); // 字符集编码

            // 发送(数据会经由 TCP、IP、以太网发送给服务器)
            OutputStream os = socket.getOutputStream();
            os.write(requestBytes);
            os.flush();

            // 请求既然已经发送,我们要做的就是等待响应
            InputStream is = socket.getInputStream();
            // 响应的前面字符集应该是 ISO-8859-1,后边是 UTF-8
            Scanner scanner = new Scanner(is, "UTF-8");
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                System.out.println(line);
            }
        }
    }
}

响应

服务器

import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MyHttpServer {
    public static void main(String[] args) throws Exception {
        // 我们也监听在 8080 端口上
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            while (true) {
                Socket socket = serverSocket.accept();  // 三次握手完成

                // 读取用户的请求 :这里就不管用户的请求了,一律采用相同的方式返回响应
                // 发送响应
                // Content-Type: 浏览器应该按照什么格式来看到我们响应的资源内容的(资源内容放在响应体中)
                // 响应体(资源的内容)
                String responseBody = "<h1>Welcome MyHttpServer</h1>";
                byte[] responseBodyBytes = responseBody.getBytes("UTF-8");
                int contentLength = responseBodyBytes.length;

                System.out.println("发送响应");
                // 响应头
                String response = "HTTP/1.0 200 OK\r\n"
                        + "Server: xxx\r\n"
                        + "Content-Type: text/plain; charset=utf-8\r\n"    // 响应体的类型
                        + "Content-Length: " + contentLength + "\r\n"      // 响应体的长度
                        + "\r\n";
                byte[] responseBytes = response.getBytes("ISO-8859-1");
                
                OutputStream os = socket.getOutputStream();
                // TCP 是面向字节流的一种协议,所以只要按顺序发即可,不要管分几次发送
                os.write(responseBytes);    // 先发送前面部分(响应行 和 响应头)
                os.write(responseBodyBytes);    // 再发送响应体
                os.flush();

                // 发送完成之后,直接关闭 TCP 连接(短连接的处理模式)
                socket.close();
            }
        }
    }
}

URI和URL

经常将ip(域名)+port 合起来称为主机 ( host)

资源路径

动态资源

URL字符的要求

HTTP请求中的关键信息 

1.请求方法
2.请求的资源路径

3.请求版本
4.请求头
5.可能存在的请求体

请求方法

演示1:通过<form>发送POST 请求

实验中涉及了两个web 资源

/post-form.html(静态资源)我们采用GET请求方法
/demo(动态)我们采用POST请求方法

演示2:

ajax请求/xhr请求 

重点!

通过JavaScript 发起HTTP请求——俗称ajax请求/xhr请求

我们使用比较频繁,尤其是在现代 web开发的前后端分离开发模式下。

使用方式(以下代码是JavaScript代码)︰

// 1. 实例化一个 XMLHttpRequest 对象,简称 XHR 对象
var xhr = new XMLHttpRequest()      // JS 语法下的实例化对象

// 2. 调用 对象 的 open(...) 方法,设置 发起请求的 1)方法   2)资源路径
//xhr.open('get', '/demo')    // GET /demo
xhr.open('post', '/demo')   // POST /demo

// 3. 设置回调函数,当 /demo 资源的响应返回时,应该干什么
// 通过事件绑定机制
// 事件源:xhr 对象
// 事件:load 事件(当响应返回时)
// 事件处理:回调函数
xhr.onload = function() {
    console.log(xhr.status)         // 打印响应的状态(成功是 200)
    console.log(xhr.responseText)   // 打印响应的响应体
    // 当然响应的其他信息我们都可以获取到,只是一般不关心
}

// 4. 真正发送请求出去
xhr.send()
<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>发起 ajax 请求</title>
</head>
<body>
    <!-- js 代码无法直接运行,必须挂靠在一个 html 上才可以 -->
    <!-- 浏览器会启动 GET /js/ajax-demo.js -->
    <!-- 并且在 JS 响应后运行 JS 代码 -->
    <!-- 运行代码过程中,会发 ajax 请求 GET /demo -->
    <!-- 最终是 3 个 HTTP 请求响应 -->
    <!-- GET /ajax-demo.html -->
    <!-- GET /js/ajax-demo.js -->
    <!-- GET /demo -->
    <script src="/js/ajax-demo.js"></script>
</body>
</html>

执行顺序

这些代码中有的是JS代码,有的是Java 代码;有的运行在浏览器进程中,有的运行在Tomcat 进程。但这些不重要的,重要的这些语句会按照一定的顺序执行。

请问执行顺序是什么∶
答:

非常常见的一道面试题

幂等性

面试题小结

演示3: 使用ajax发送post+携带请求体的请求

GET在query string中无论携带什么数据,总体上还是得遵守key=value的形式。但post则非常灵活。

使用ajax发送post+携带请求体的请求。

@Controller
public class MyController {
    @RequestMapping("/collect")
    @ResponseBody
    public String collect() {
        return "OK";
    }
}
var xhr = new XMLHttpRequest()
xhr.open('post', '/collect')
xhr.onload = function() {
    console.log(xhr)
    console.log(this)
}

// 区别在这里
xhr.setRequestHeader('Content-Type', 'text/xxxxxxx')
xhr.send('我随便写,按照 content-type 的格式去写就行')
<!DOCTYPE html>
<html lang="zh-hans">
<head>
    <meta charset="UTF-8">
    <title>发送有请求体的 ajax 请求</title>
</head>
<body>
    <script src="/js/ajax-send-request-body.js"></script>
</body>
</html>

form表单逻辑上只是一种提交数据的形式。但实际中使用较多,所以form提交的一些行为,代替了get/post 请求的行为。

HTTP响应中的关键信息  

重定向

重定向分类

 

同理,通过 ajax发起HTTP 404或者其他错误,你是无法在页面中直接看到错误的,所以打开开发者工具去查看。

响应头

form表单提交

总之,文件上传时(通过form表单上传),必须指定enctype为multipart/form-data这样,请求体中才不仅仅携带要上传文件的文件名,还包含文件内容信息。这样,后端才可以读取到信息,做进—步处理。

小结

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到