Linux——HTTP协议

目录

HTTP协议

HTTP结构

HTTP请求

请求方法

URL

HTTP版本

换行符

请求报头

HTTP响应

HTTP版本

状态码&状态码描述

地址重定向

一个简单的HTTP服务


只有认知的突破 💫才能带来真正的成长 💫编程技术的学习 💫没有捷径 💫一起加油💫

🍁感谢各位的观看 🍁欢迎大家留言 🍁咱们一起加油 🍁努力成为更好的自己🍁

HTTP协议

HTTP结构

HTTP就是一个结构体,学习HTTP协议,就是学习它每个属性的含义。HTTP协议由两部分组成,HTTP请求协议和HTTP响应协议。如下图所示。

HTTP请求

对于HTTP请求,就是讲解红色圈的内容。

请求方法

GET,POST,PUT,DELETE

  • GET:用于获取一些资源,比如:获取一个登录页面。它的参数是拼接在URL链接后面的。

  • POST:用于提交资源/创建资源,比如:上传一个文件,提交一个订单。它的参数保存在data中,相比于GET,要稍安全一些。

  • PUT:传输文件。

  • DELETE:删除一些资源。

URL

对于HTTP的端口号,是被HTTP内定的,所以请求的时候,浏览器会默认给加上端口号,不需要显示输入。

  • /:它是web根目录。
HTTP版本
  • 现在的版本主要是1.0和1.1版本,前后端的HTTP版本,要一致,否则无法通信。
换行符
  • "\r\n"
请求报头
  • Host:指定请求要发送到的目标域名。

  • Connection: keep-alive:表示希望保持 TCP 连接不立即关闭,以便后续请求可以复用这个连接,提升传输效率。

  • Content-Length:表示请求体(body/data)的字节,让服务器知道需要读取多少字节的数据。

  • Origin:表明请求的来源域名,主要用于跨域请求(CORS)的验证,服务器会根据这个值判断是否允许跨域。

  • Content-Type: application/x-www-form-urlencoded,表示请求体中的数据是 key=value 形式的 URL 编码格式。

  • User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36,显示自己的机器信息。

    • 这个头字段告诉服务器,发起请求的客户端是 Windows 8.1 系统上的 Chrome 61 浏览器,服务器可以据此返回适配该浏览器的内容。
  • Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

HTTP响应
HTTP版本
  • 现在的版本主要是1.0和1.1版本,前后端的HTTP版本,要一致,否则无法通信。
状态码&状态码描述

常用的状态码及其状态码描述,如下表格所示。

|-----|----------------------------|---------------------------------------------------|
| 状态码 | 状态码描述 | 应用样例 |
| 200 | OK | 访问网站成功,服务器返回网页的内容 |
| 201 | Created | 发布新文章,服务器返回文章资源创建成功的信息 |
| 301 | Moved Permanently(永久搬家) | 这个网页已经永久搬家到新地址了,以后别再来老地址找它了。 |
| 302 | Found / See Other(临时跳转) | 这个网页只是临时不在这,你去新地址看看,但下次有需求还是可以先来老地址问问。 |
| 304 | Not Modified(没变化,用缓存吧) | 你之前已经来过了,这个网页从上次之后就没更新过,直接用你本地缓存的版本就行,不用重新下载。 |
| 400 | Bad Request(请求格式错了) | 你提交的内容格式不对,服务器看不懂,所以拒绝处理。 |
| 401 | Unauthorized(你还没登录 / 身份失效) | 你访问的页面需要登录,但你还没登录,或者登录状态已经过期了。 |
| 403 | 403 Forbidden(你没权限看) | 你已经登录了,但这个页面 / 资源你没有权限访问,服务器直接拒绝。 |

|-----|---------------------------------|--------------------------------|
| 404 | Not Found(找不到这个页面) | 你访问的链接不存在,可能是地址输错了,或者页面被删除了。 |
| 500 | Internal Server Error(服务器自己出问题了 | 不是你的问题,是服务器内部出错了,比如代码崩溃、数据库挂了。 |

地址重定向

HTTP状态码301(永久重定向)和302(临时重定向)都依赖Location选项。

服务器会在HTTP响应中,增加个Location选项,在该选项后面放上要重定向的URL,客户端读取到Location的时候,会自动访问这个链接,自动重定向。

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

一个简单的HTTP服务

如下所示的简单HTTP后端服务代码。请求成功以后,会返回一个简单的登录html页面.

httpServer.cc

cpp 复制代码
// 包含必要的头文件
#include <iostream>       // 用于输入输出操作
#include <cstring>        // 用于字符串操作
#include <unistd.h>       // 用于POSIX系统调用
#include <sys/socket.h>   // 用于套接字操作
#include <netinet/in.h>   // 用于网络地址结构
#include <arpa/inet.h>    // 用于IP地址转换

// 定义服务器端口和缓冲区大小
const int PORT = 8888;     // 服务器监听端口
const int BUFFER_SIZE = 1024; // 客户端请求缓冲区大小

int main() {
    // 定义服务器和客户端套接字文件描述符
    int server_fd, client_fd;
    // 定义服务器和客户端地址结构
    struct sockaddr_in server_addr, client_addr;
    // 定义客户端地址长度
    socklen_t client_len = sizeof(client_addr);
    // 定义缓冲区,用于存储客户端请求
    char buffer[BUFFER_SIZE];
    
    // 定义登录页面的HTML内容
    const char* html_content = 
        "<!DOCTYPE html>\n"
        "<html>\n"
        "<head>\n"
        "<title>Login Page</title>\n"
        "<style>\n"
        "body { font-family: Arial, sans-serif; margin: 0; padding: 0; background-color: #f4f4f4; }\n"
        ".login-container { width: 300px; margin: 100px auto; background-color: white; padding: 20px; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); }\n"
        "h2 { text-align: center; margin-bottom: 20px; }\n"
        ".form-group { margin-bottom: 15px; }\n"
        "label { display: block; margin-bottom: 5px; }\n"
        "input[type='text'], input[type='password'] { width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 3px; }\n"
        "input[type='submit'] { width: 100%; padding: 10px; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; }\n"
        "input[type='submit']:hover { background-color: #45a049; }\n"
        "</style>\n"
        "</head>\n"
        "<body>\n"
        "<div class='login-container'>\n"
        "<h2>Login</h2>\n"
        "<form action='#' method='post'>\n"
        "<div class='form-group'>\n"
        "<label for='username'>Username:</label>\n"
        "<input type='text' id='username' name='username' required>\n"
        "</div>\n"
        "<div class='form-group'>\n"
        "<label for='password'>Password:</label>\n"
        "<input type='password' id='password' name='password' required>\n"
        "</div>\n"
        "<input type='submit' value='Login'>\n"
        "</form>\n"
        "</div>\n"
        "</body>\n"
        "</html>";
    
    // 构建完整的HTTP响应
    // 包含HTTP状态行、响应头和响应体
    std::string http_response = 
        "HTTP/1.1 200 OK\r\n"                // HTTP状态行,200表示成功
        "Content-Type: text/html\r\n"         // 响应头,指定内容类型为HTML
        "Content-Length: " + std::to_string(strlen(html_content)) + "\r\n"  // 响应头,指定内容长度
        "Connection: close\r\n"               // 响应头,指定连接关闭
        "\r\n" +                              // 空行,分隔响应头和响应体
        std::string(html_content);              // 响应体,登录页面HTML内容
    
    // 创建服务器套接字
    // AF_INET: 使用IPv4协议
    // SOCK_STREAM: 使用TCP协议
    // 0: 使用默认协议
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        std::cerr << "Socket creation failed" << std::endl;
        return 1;
    }
    
    // 设置套接字选项
    // SOL_SOCKET: 套接字级别
    // SO_REUSEADDR: 允许重用本地地址和端口
    // opt: 1表示启用该选项
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
        std::cerr << "setsockopt failed" << std::endl;
        return 1;
    }
    
    // 配置服务器地址结构
    server_addr.sin_family = AF_INET;              // 使用IPv4协议
    server_addr.sin_addr.s_addr = INADDR_ANY;      // 监听所有网络接口
    server_addr.sin_port = htons(PORT);            // 转换端口号为网络字节序
    
    // 绑定服务器套接字到指定地址和端口
    if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        std::cerr << "Bind failed" << std::endl;
        return 1;
    }
    
    // 开始监听客户端连接
    // 5: 最大连接队列长度
    if (listen(server_fd, 5) < 0) {
        std::cerr << "Listen failed" << std::endl;
        return 1;
    }
    
    // 输出服务器启动信息
    std::cout << "Server listening on port " << PORT << "..." << std::endl;
    
    // 主循环,不断接受和处理客户端连接
    while (true) {
        // 接受客户端连接
        // server_fd: 服务器套接字
        // (struct sockaddr*)&client_addr: 客户端地址结构
        // &client_len: 客户端地址长度
        client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd < 0) {
            std::cerr << "Accept failed" << std::endl;
            continue; // 继续下一次循环,接受下一个连接
        }
        
        // 读取客户端请求
        ssize_t bytes_read = read(client_fd, buffer, BUFFER_SIZE - 1);
        if (bytes_read > 0) {
            // 为缓冲区添加结束符,防止字符串溢出
            buffer[bytes_read] = '\0';
            // 发送HTTP响应给客户端
            send(client_fd, http_response.c_str(), http_response.size(), 0);
        }
        
        // 关闭客户端连接
        close(client_fd);
    }
    
    // 关闭服务器套接字(实际上不会执行到这里,因为主循环是无限的)
    close(server_fd);
    return 0;
}
相关推荐
**蓝桉**2 小时前
Prometheus时间出现误差
linux·运维·prometheus
自在极意功。2 小时前
TCP三次握手与四次挥手
网络·网络协议·tcp/ip·计算机网络·三次握手·四次挥手
vortex52 小时前
文件上传漏洞绕过技术总结(含实操指南与防御方案)
linux·服务器·网络安全·渗透测试
知无不研2 小时前
c++垃圾回收机制
开发语言·c++·智能指针·raii·垃圾回收机制
_dindong2 小时前
【单调栈/队列&并查集&字符串哈希&Tire树】习题集锦
数据结构·c++·算法·哈希算法
西装没钱买2 小时前
QT组播的建立和使用(绑定特定的网卡,绑定特定IP)
网络·c++·qt·udp·udp组播
江畔何人初2 小时前
HPA是如何在k8s集群实现自动扩缩容机制的
linux·运维·服务器·云原生·kubernetes
杨云龙UP3 小时前
Oracle 19c RAC多节点运行状态最简排查指南_20260316
linux·运维·服务器·数据库·sql·oracle
Ralph_Y3 小时前
C++:static
开发语言·c++