• HTTP协议详解



    提示:以下是本篇文章正文内容,Java系列学习将会持续更新

    一、HTTP工作过程

    HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的应用层协议。

    1.基于某个特定的传输层协议(TCP)之上
    2.描述业务
    3.非OS系统

    当我们在浏览器中输入一个 “网址”, 此时浏览器就会给对应的服务器发送一个 HTTP 请求. 对方服务器收到这个请求之后, 经过计算处理, 就会返回一个 HTTP 响应。
    在这里插入图片描述
    事实上, 当我们访问一个网站的时候, 可能涉及不止一次的 HTTP 请求/响应 的交互过程。

    回到目录…

    二、HTTP 协议格式

    请添加图片描述
    注意: 为什么 HTTP 报文中要存在空行呢?

    • 因为 HTTP 协议并没有规定报头部分的键值对有多少个,使用空行就相当于是报文的结束标记或报文和正文之间的分隔符
    • HTTP 在传输层依赖 TCP 协议,TCP 是面向字节流的。如果没有这个空行,就会出现”粘包问题“

    回到目录…

    2-1 请求(Request)格式

    在这里插入图片描述

    2-1-1 URL格式

    URL (Uniform Resource Locator 统一资源定位符),互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
    请添加图片描述
    URL的具体格式:

    1. 资源在哪台主机上——域名 (domain) 或者ip来体现一主机 (host)
    2. 和主机上的哪个进程去获取资源——端口 (port)
    3. 具体定位到是该进程管理的哪个资源——资源路径/路径 (path)
    4. URL设计之处,不仅仅为HTTP协议使用。所以需要标识出本次资源对应的协议(protocol / schema)
    5. 针对本次请求,除了资源本身之外的特殊要求。(查询字符串 query string、文档片段 fragment)

    回到目录…

    2-1-2 方法(method)

    方法说明适用版本号
    GET获取资源HTTP 1.0、HTTP 1.1
    POST传输实体主体HTTP 1.0、HTTP 1.1
    PUT传输文件HTTP 1.0、HTTP 1.1
    HEAD获得报文首部HTTP 1.0、HTTP 1.1
    DELETE删除文件HTTP 1.0、HTTP 1.1
    OPTIONS访问支持的方法HTTP 1.1
    TRACE追踪路径HTTP 1.1
    CONNECT要求用隧道协议连接代理HTTP 1.1
    LINK建立和资源之间的联系HTTP 1.1
    UNLINE断开连接关系HTTP 1.1

    2-1-2-1 GET 方法

    GET 是最常用的 HTTP 方法,常用于获取服务器上的某个资源。

    GET 请求的特点:

    • 首行里面的第一个部分就是 GET
    • URL 里面的 query string 可以为空,也可以不为空 %E8%9B%8B%E7%B3%95
    • GET 请求的 header 有若干个键值对结构
    • GET 请求的 body 一般是空的

    GET 请求示例: 搜狗首页请求
    在这里插入图片描述

    2-1-2-2 POST 方法

    POST 方法也是一种常见的方法,多用于提交用户输入的数据给服务器(如登录页面)。

    POST 请求的特点:

    • 首行第一个部分就是 POST
    • URL 里面的 query string 一般是空的
    • POST 请求的 header 里面有若干个键值对
    • POST 请求的 body 一般不为空(body 的具体数据格式,由 header 中的 Content-Type 来描述; body 的具体数据长度,由 header 中的 Content-Length 来描述

    POST 请求示例: QQ 邮箱登录请求
    在这里插入图片描述

    面试题:GET 和 POST 的区别

    • GET 和 POST 其实没有本质区别,使用 GET 的场景完全可以使用 POST 代替,使用 POST 的场景一样可以使用 GET 代替。但是在具体的使用上,还是存在一些细节的区别

    • GET 习惯上会把客户端的数据通过 query string 来传输(body 部分是空的);POST 习惯上会把客户端的数据通过 body 来传输(query string 部分是空的)

    • GET 习惯上用于从服务器获取数据;POST 习惯上是客户端给服务器提交数据

    • 一般情况,程序员会把 GET 请求的处理,实现成“幂等”的;对于 POST 请求的处理,不要求实现成“幂等”

    • GET 请求可以被缓存,可以被浏览器保存到收藏夹中;POST 请求不能被缓存

    2-1-3 协议头(header)

    header 的整体格式是键值对结构,每个键值对占一行,键和值之间使用 冒号+空格 进行分割

    keyvalue
    Host表示服务器主机的地址和端口
    Content-Length表示 body 的数据长度,长度单位是字节
    Content-Type表示 body 的数据格式
    User-Agent表示浏览器或者操作系统的属性
    Referer表示这个页面是从哪个页面跳转过来的
    Cookie是浏览器提供的一种让程序员在本地存储数据的能力

    Content-Type 有以下三种请求中的数据格式:

    • application/x-www-form-urlencoded

    这是 form 表单提交的数据格式,此时 body 的格式就类似于 query string(是键值对的结构,键值对之间使用 & 分割,键与值之间使用 = 分割

    • multipart/form-data

    这是 form 表单提交的数据格式(需要在 from 标签上加上 enctyped="multipart/form-data"),通常用于 HTML 提交图片或者文件

    • application/json

    此时 body 数据为 json 格式,json 格式就是源自 js 的对象的格式。用一个 { } 括住,里面有多个键值对,键值对之间使用逗号分割,键和值之间使用冒号分割

    回到目录…

    2-2 响应(Response)格式

    在这里插入图片描述

    2-2-1 状态码

    在这里插入图片描述

    2-2-2 协议头(header)

    响应报头的基本格式和请求报头的格式基本一致。

    下面介绍下响应报头的 Content-Type 参数

    • text/html

    表示数据格式是 HTML

    • text/css

    表示数据格式是 CSS

    • application/javascript

    表示数据各式是 JavaScript

    • application/json

    表示数据格式是 JSON

    回到目录…

    三、手写HTTP

    3-1 HTTP客户端

    import java.io.*;
    import java.net.Socket;
    // HTTP 客户端
    public class HTTPClient {
        public static void main(String[] args) throws IOException {
            // 1. HTTP 客户端,要发送 HTTP 请求,先建立 TCP 连接
            // 我们当前进程和www.baidu.com主机上绑定 8080 端口的进程使用 TCP 通信(要求 建立 TCP 连接)
            Socket socket = new Socket("localhost", 80);
    
            OutputStream os = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
    
            // 只有请求行,请求头为空,没有请求体
            String request = "GET / HTTP/1.0\r\n\r\n";
            writer.print(request);
            // 冲刷缓冲区
            writer.flush();
    
            // 读取百度返回的 HTTP 响应
            InputStream is = socket.getInputStream();
            byte[] buf = new byte[10240];    // 我们知道响应不会超过 1024 字节的
            int n = is.read(buf);
            String response = new String(buf, 0, n, "UTF-8");
            System.out.println(response);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    3-2 HTTP服务端

    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.ServerSocket;
    import java.net.Socket;
    // HTTP 服务端
    public class HTTPServer {
        public static void main(String[] args) throws IOException {
            // 我们使用短连接
            ServerSocket serverSocket = new ServerSocket(80);
            while (true) {
                try {
                    Socket socket = serverSocket.accept();
                    // 不管对方发给我们的 请求 是什么,一律使用统一的响应回复对方
                    OutputStream os = socket.getOutputStream();
                    PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
                    String html = "百度一下";   // 我们的响应体
                    byte[] bytes = html.getBytes("UTF-8");
                    int contentLength = bytes.length;
                    String response = "HTTP/1.0 200 OK\r\n" +
                            "Content-Type: application/octet-stream; charset=utf-8\r\n" +
                            "Content-Length: 49\r\n" +
                            "\r\n" +
                            html;
    
                    writer.print(response);
                    writer.flush();
    
                    socket.close();
                } catch (IOException exc) {
                    exc.printStackTrace();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    回到目录…


    总结:
    提示:这里对文章进行总结:
    以上就是今天的学习内容,本文是HTTP协议的学习,了解HTTP协议的工作过程,HTTP的请求和响应格式,以及如何手写HTTP服务器。之后的学习内容将持续更新!!!

  • 相关阅读:
    GIS数据漫谈(六)— 投影坐标系统
    【ESP-IDF环境搭建,下载编译第一个程序】
    您的应用存在隐藏最近任务列表名称的行为,不符合华为应用市场审核标准
    数据结构-例题实训作业-二叉树相关
    ArgoCD 用户管理、RBAC 控制、脚本登录、App 同步
    iptables防火墙
    聊聊Android线程优化这件事
    AI绘图—对中文拟合度很高,值得一试
    无用自动化测试?
    sklearn快速入门教程:独热编码
  • 原文地址:https://blog.csdn.net/qq15035899256/article/details/126103840