应⽤层协议HTTP

发布于:2025-08-06 ⋅ 阅读:(19) ⋅ 点赞:(0)

HTTP协议

虽然我们说,应⽤层协议是我们程序猿⾃⼰定的.但实际上,已经有⼤佬们定义了⼀些现成的,⼜⾮常好
⽤的应⽤层协议,供我们直接参考使⽤.HTTP(超⽂本传输协议)就是其中之⼀。

在互联⽹世界中,HTTP(HyperText Transfer Protocol,超⽂本传输协议)是⼀个⾄关重要的协议。
它定义了客⼾端(如浏览器)与服务器之间如何通信,以交换或传输超⽂本(如HTML⽂档)。

  • HTTP协议是客⼾端与服务器之间通信的基础。
  • 客⼾端通过HTTP协议向服务器发送请求,服务器收到请求后处理并返回响应。
  • HTTP协议是⼀个⽆连接、⽆状态的协议,即每次请求都需要建⽴新的连接,且服务器不会保存客⼾端的状态信息

认识URL

平时我们俗称的"⽹址"其实就是说的URL
在这里插入图片描述

urlencode和urldecode

像/ ? :等这样的字符,已经被 url 当做特殊意义理解了.因此这些字符不能随意出现.
⽐如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进⾏转义.
转义的规则如下:
将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做⼀位,前⾯加
上%,编码成%XY格式
例如:
在这里插入图片描述
“+“被转义成了”%2B”
urldecode就是urlencode的逆过程;
urllencode工具

HTTP协议请求与响应格式

HTTP请求

在这里插入图片描述

  • ⾸⾏: [⽅法] + [url] + [版本]
  • Header:请求的属性,冒号分割的键值对;每组属性之间使⽤ \r\n 分隔;遇到空⾏表⽰ Header
    部分结束
  • Body:空⾏后⾯的内容都是Body.Body允许为空字符串.如果Body存在,则在Header中会有⼀个
    Content-Length属性来标识Body的⻓度;
    在这里插入图片描述

HTTP响应

在这里插入图片描述

  • ⾸⾏: [版本号] + [状态码] + [状态码解释]
  • Header: 请求的属性,冒号分割的键值对;每组属性之间使⽤\r\n分隔;遇到空⾏表⽰Header部分结
  • Body:空⾏后⾯的内容都是Body.Body允许为空字符串.如果Body存在,则在Header中会有⼀个
    Content-Length属性来标识Body的⻓度;如果服务器返回了⼀个html⻚⾯,那么html⻚⾯内容就
    是在body中.

HTTP的⽅法

其中最常⽤的就是GET⽅法和POST⽅法

GET⽅法

⽤途:⽤于请求URL指定的资源。

⽰例: GET /index.html HTTP/1.1

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

POST⽅法

⽤途:⽤于传输实体的主体,通常⽤于提交表单数据。

⽰例: POST /submit.cgi HTTP/1.1

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

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等。

HTTP的状态码

在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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

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

  • 当服务器返 HTTP 301状态码时,表⽰请求的资源已经被永久移动到新的位置。
  • 在这种情况下,服务器会在响应中添加⼀个Location头部,⽤于指定资源的新位置。这个Location
    头部包含了新的URL地址,浏览器会⾃动重定向到该地址。
    例如,在HTTP响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 301 Moved Permanently\r\n
Location: https://www.new-url.com\r\n

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

  • 当服务器返回 HTTP 302状态码时,表⽰请求的资源临时被移动到新的位置。
  • 同样地,服务器也会在响应中添加⼀个Location头部来指定资源的新位置。浏览器会暂时使⽤新的
    URL进⾏后续的请求,但不会缓存这个重定向。
    例如,在HTTP响应中,可能会看到类似于以下的头部信息:
HTTP/1.1 302 Found\r\n
Location: https://www.new-url.com\r\n

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

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连接。

下⾯附上⼀张关于HTTP常⻅header的表格
在这里插入图片描述

最简单的HTTP服务器

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

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

#define default_backlog 5

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        std::cout << "Usage " << argv[0] << " ip port" << std::endl;
        exit(1);
    }

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if(sock < 0)
        exit(1);
    
    std::string ip = argv[1];
    uint16_t port = std::stoi(argv[2]);

    sockaddr_in addr;
    bzero(&addr, sizeof(addr));
    addr.sin_addr.s_addr = inet_addr(ip.c_str());
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);

    int b = bind(sock, (const sockaddr*)&addr, sizeof(addr));
    if(b < 0)
        exit(1);

    int l = listen(sock, default_backlog);
    if(l < 0)
        exit(1);

    while(true)
    {
        sockaddr_in client_addr;
        socklen_t len;

        int sockfd = accept(sock, (sockaddr*)&client_addr, &len);
        if(sockfd < 0)
            continue;
        
        char input_buffer[5120] = { 0 };
        int r = read(sockfd, input_buffer, sizeof(input_buffer) - 1);
        if(r < 0)
            return 1;
        
        std::cout << "[Request] " << input_buffer << std::endl;

        char buffer[1024] = { 0 };
        const char* hello = "<h1>Hello World</h1>";

        sprintf(buffer, "HTTP /1.0 200 OK\nContent-Length: %lu\n\n%s", strlen(hello), hello);

        write(sockfd, buffer, sizeof(buffer));
    }

    return 0;
}

在这里插入图片描述
在这里插入图片描述

此处我们使⽤8081端⼝号启动了HTTP服务器.虽然HTTP服务器⼀般使⽤80端⼝,
但这只是⼀个通⽤的习惯.并不是说HTTP服务器就不能使⽤其他的端⼝号.

favicon.ico 是⼀个⽹站图标,通常显⽰在浏览器的标签⻚上、地址栏旁边或收藏夹中。
这个图标的⽂件名favicon 是"favorite icon" 的缩写,⽽ .ico 是图标的⽂件格式。
浏览器在发起请求的时候,也会为了获取图标⽽专⻔构建http请求,我们不管它。


网站公告

今日签到

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