计算机网络之应用层协议HTTP

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

应用层协议HTTP

收录于专栏【计算机网络
本专栏旨在分享学习计算机网络的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

[1. HTTP 简单介绍](#1. HTTP 简单介绍)

[2. 认识 URL](#2. 认识 URL)

[urlencode 和 urldecode](#urlencode 和 urldecode)

[3. HTTP 协议请求与响应格式](#3. HTTP 协议请求与响应格式)

[HTTP 请求](#HTTP 请求)

[​编辑 HTTP 响应](#编辑 HTTP 响应)

[​编辑4. HTTP方法](#编辑4. HTTP方法)

[HTTP 常见方法](#HTTP 常见方法)

[GET 方法](#GET 方法)

[POST 方法](#POST 方法)

[PUT 方法](#PUT 方法)

[HEAD 方法](#HEAD 方法)

[DELETE 方法](#DELETE 方法)

[OPTIONS 方法](#OPTIONS 方法)

[5. HTTP 的状态码](#5. HTTP 的状态码)

[6. HTTP 常见 Header](#6. HTTP 常见 Header)

[关于 connection 报头](#关于 connection 报头)

[7. 实现最简单的 HTTP 服务器](#7. 实现最简单的 HTTP 服务器)


1. HTTP 简单介绍

虽然我们说, 应用层协议是我们程序猿自己定的, 但实际上, 已将有大佬定义了一些现成的, 有非常好用的应用层协议, 供我们直接参考使用, **HTTP (超文本传输协议)**就是其中之一.

在互联网世界中, HTTP (HyperText Transfer Protocol , 超文本传输协议) 是一个至关重要的协议, 它定义了客户端 (如浏览器) 与服务器之间如果通信, 以交换或传输超文本 (如 HTML文档)

HTTP 协议是客户端与服务器之间通信的基础, 客户端通过 HTTP 协议向服务器发送请求, 服务器收到请求后处理并返回响应, HTTP 协议是一个无连接, 无状态的协议, 及每次请求都需要建立连接, 且服务器不会保存客户端的信息状态.

2. 认识 URL

平时我们俗称的 "网址" 其实就是说的 "URL"

urlencode 和 urldecode

像 /? : 等这样的字符, 已经被 url 当做特殊意义理解了. 因此这些字符不能随意出现.

比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

转义的规则如下 :

将需要转码的字符转为 : 16 进制, 然后从右到左, 取 4 位 (不足 4 位直接处理), 每 2 位做一位, 前面加上 %, 编码成 %XY 格式

例如 :

"+" 被转义成了 "%2B"

urldecode 就是 urlencode 的逆过程

3. HTTP 协议请求与响应格式

HTTP 请求

首行 : [方法] + [url] + [版本]

Header : 请求的属性, 冒号分割的键值对, 每组属性之间使用 \r\n 分隔, 遇到空行表示 Header 部分结束

**Body :**空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, Header 中会有一个 Content-Lengths 属性来标识 Body 的长度

HTTP 响应

首行 :[版本号] + [状态码] + [状态码解释]

**Header :**请求的属性, 冒号分割的键值对, 每组属性之间使用 \r\n 分隔, 遇到空行表示 Header 部分结束

**Body :**空行后面的内容都是 Body. Body 允许为空字符串, 如果 Body 存在, 则在 Header 中会有一个 Content-Length 属性来标识 Body 的长度, 如果服务器返回了一个 html 页面, 那么 html 页面内容就是在 body 中.

4. HTTP方法

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

其中常用的就是 GET 方法和 POST 方法.

HTTP 常见方法

GET 方法

**用途 :**用于请求 URL 指定的资源

**示例 :**GET /index.html HTTP/1.1

**特性 :**指定资源服务器端解析后返回响应内容

**from表单 :**https://www.runoob.com.html/html-froms.html

POST 方法

**用途 :**用于传输实体的主体, 通常用于提交表单数据.

**示例 :**POST /submit.cgi HTTP/1.1

特性 : 可以发送大量的数据给服务器, 并且数据包含在请求中.

from表单 : https://www.runoob.com.html/html-froms.html

PUT 方法

用途 : 用于传输文件, 将请求文主体中的文件保存到请求 URL 指定的位置

**示例 :**PUT /example.html HTTP/1.1

**特性 :**不太常用, 但在某些情况下, 如 RESTful API 中, 用于更新资源.

HEAD 方法

**用途 :**与 GET 方法类似, 烦不烦会报文主体部分, 仅返回响应头

**示例 :**HEAD /index.html HTTP/1.1

**特性 :**用于确认 URL 的有效性以及资源更新的日期时间等

DELETE 方法

**用途 :**用于删除文件, 是 PUT 的相反方法

**示例 :**DELETE /example.html HTTP/1.1

**特性 :**按请求 URL 删除指定的资源

OPTIONS 方法

**用途 :**用于查询针对请求 URL 指定的资源支持的方法

**示例 :**OPTIONS * HTTP/1.1

特性 : 返回允许的方法, 如 GET, POST 等

5. HTTP 的状态码

类别 原因短语
1XX Informational (信息性状态码) 接受的请求正在处理
2XX Success (成功状态码) 请求正常处理完毕
3XX Redirection (重定向状态码) 需要进行附加操作加以完成请求
4XX Cilent Error (客户端错误状态码) 服务器无法处理请求
5XX Server Error (服务器错误状态码) 服务器处理请求出错

最常见状态码, 比如200(OK), 404(Not Found), 403(Forbidden), 302(Redirect, 重定向), 504(Bad Gateway)

HTTP 状态码 301 (永久重定向) 和 302 (临时重定向) 都依赖 Location 选项, 以下是关于两者依赖 Location 选项的详细说明 :

HTTP 状态码 301 (永久重定向) :

当服务器返回 HTTP 301 状态码时, 表示请求的资源已经被永久移动到新的位置

这种情况下, 服务器会在响应中添加一个 Location 头部, 用于指定资源的新位置, 这个 Location 头部包含了新的 URL 地址, 浏览器会自动重定向到该地址.

例如, 在 HTTP 响应中, 可能会看到类似于以下的头部信息 :

cpp 复制代码
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\n

HTTP 状态码 302 (临时重定向) :

当服务器返回 HTTP 302 状态码时, 表示请求的资源临时被移动到新的位置.

同样地, 服务器也会在响应中添加一个 Location 头部来指定资源的新位置, 浏览器会暂时使用新的 URL 进行后续的请求, 但不会缓存这个重定向.

例如 : 在 HTTP 响应中, 可能会看到类似于以下的头部信息 :

cpp 复制代码
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n

**总结 :**无论是 HTTP 301 还是 HTTP 302 重定向, 都需呀依赖 Location 选项来指定资源的新位置. 这个 Location 选项是一个标准的 HTTP 响应头部, 用于告诉浏览器应该将请求重定向到哪个新的 URL 地址.

6. HTTP 常见 Header

**Content-Type :**数据类型 (text/html 等)

**Content-Length :**Body 的长度

**Host :**客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上

**User-Agent :**声明用户的操作系统和浏览器版本信息

**referer :**当前页面是从哪个页面跳转过来的

**Location :**搭配 3XX 状态码使用, 告诉客户端接下来要去哪里访问

**Cookie :**用于在客户端存储少量信息, 通常用于实现会话 (session) 的功能

关于 connection 报头

HTTP 中的 Connection 字段是 HTTP 报文头的一部分, 它主要用于控制和管理客户端与服务器之间的连接状态

核心作用

**管理持久连接 :**Connection 字段还用于管理持久连接 (也称为长连接). 持久连接允许客户端和服务器在请求/响应完成之后不立即关闭 TCP 连接, 以便在同一个连接上发送多个请求和接收多个响应.

持久连接 (长连接)

**HTTP/1.1 :**在HTTP/1.1 协议中, 默认使用持久连接, 当客户端和服务器都不明确指定关闭连接时, 连接将保持打开状态, 以便后续的请求和响应可以复用同一个连接

**HTTP/1.0 :**在 HTTP/1.0 协议中, 默认连接是非持久的. 如果希望在 HTTP/1.0 上实现持久连接, 需要在请求头中显示设置 Connection : keep-alive

语法格式 :

Connection : keep-alive : 表示希望保持连接以服用 TCP 连接

Connection : close : 表示请求/响应完成后, 应该关闭 TCP 连接

7. 实现最简单的 HTTP 服务器

实现一个最简单的 HTTP 服务器, 只在网页上输出 "hello world", 只要我们按照 HTTP 协议的要求构造数据, 就很容易做到

cpp 复制代码
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void Usage()
{
    printf("usage : ./server [ip] [port]\n");
}

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        Usage();
        return 1;
    }

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd < 0)
    {
        perror("socket");
        return 1;
    }
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    addr.sin_port = htons(atoi(argv[2]));

    int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
    if(ret < 0)
    {
        perror("bind");
        return 1;
    }
    ret = listen(fd, 10);
    if(ret < 0)
    {
        perror("listen");
        return 1;
    }
    for(;;)
    {
        struct sockaddr_in client_addr;
        socklen_t len;
        int client_fd = accept(fd, (struct sockaddr*)&client_addr, &len);
        if(client_fd < 0)
        {
            perror("accept");
            continue;
        }
        char input_buf[1024 * 10] = {0}; // 用一个足够大的缓冲区直接把数据读完
        ssize_t read_size = read(client_fd, input_buf, sizeof(input_buf) - 1);
        if(read_size < 0)
        {
            return 1;
        }
        printf("[Request] %s", input_buf);
        char buf[1024] = {0};
        const char* hello = "<h1>hello world</h1>";
        sprintf(buf, "HTTP/1.0 200 OK\nContent-Length:%lu\n\n%s", strlen(hello), hello);
        write(client_fd, buf, strlen(buf));
    }
    return 0;
}
相关推荐
R-G-B9 分钟前
【03】MFC入门到精通——MFC 添加控件 设置属性 按钮 文本框
c++·mfc·mfc添加控件
渡我白衣19 分钟前
Linux操作系统之进程间通信:管道概念
linux
liulilittle23 分钟前
C/C++ inline-hook(x86)高级函数内联钩子
c语言·开发语言·汇编·c++·hook·底层·钩子
Amelio_Ming25 分钟前
C++开源项目—2048.cpp
linux·开发语言·c++
chilavert31828 分钟前
技术演进中的开发沉思-28 MFC系列:关于C++
开发语言·c++·mfc
GiraKoo36 分钟前
【GiraKoo】C++ 右值引用 (Rvalue Reference)
c++
搬砖天才、42 分钟前
SpringGateway网关增加https证书验证
网络协议·http·https
cui_win42 分钟前
【网络】Linux 内核优化实战 - net.ipv4.tcp_dsack
linux·网络·tcp/ip
2501_915374351 小时前
WHIP(WebRTC HTTP Ingestion Protocol)详解
网络协议·tcp/ip·udp
让我们一起加油好吗1 小时前
【C++】容器适配器 + stack/queue/deque详解
c++·stl·适配器模式·deque·queue·stack