当前位置: 首页 > ai >正文

【Linux网络】HTTP协议全解析 - 从请求响应到方法与Header

📢博客主页:https://blog.csdn.net/2301_779549673
📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨

在这里插入图片描述

在这里插入图片描述

文章目录

  • 🏳️‍🌈一、应用层协议Http
    • 1.1 Http协议
    • 1.2 URL
    • 1.2 urlencode 和 urldecode
  • 🏳️‍🌈二、模拟 HTTP 协议请求与响应
    • 2.1 修改代码
      • 2.1.1 TcpSever.hpp
      • 2.1.2 Http.hpp
      • 2.1.3 TcpServer.cpp
    • 2.2 模拟window客户端访问服务端
    • 2.3 模拟通过浏览器访问
  • 🏳️‍🌈三、HTTP 协议请求与响应格式
    • 2.1 Http 请求格式
    • 2.2 Http 响应格式
  • 🏳️‍🌈四、Http方法
    • 4.1 Http 常用方法
    • 4.2 HTTP 的状态码
    • 4.3 HTTP 常见 Header
  • 👥总结


11111111
11111111
11111111
11111111
**** 11111111

🏳️‍🌈一、应用层协议Http

1.1 Http协议

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

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

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

1.2 URL

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

在这里插入图片描述

1.2 urlencode 和 urldecode

/?: 等这样的字符,已经被 url 当做特殊意义理解了。因此这些字符不能随意出现,比如,某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义

转义的规则如下:

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

在这里插入图片描述
urlencode工具

在这里插入图片描述

使用特殊字符访问浏览器时,会进行 编码(urlencode)解码(urldecode) 的过程!

🏳️‍🌈二、模拟 HTTP 协议请求与响应

2.1 修改代码

我们将我们上一篇文章中用到的 网络计算机 中所有的代码直接搬过来修改 传送门

2.1.1 TcpSever.hpp

这部分,我们去掉 网络计算机序列化处理请求以及计算功能将回调函数就设置为简单回显客户端的ip和端口号

需要修改的部分

using service_t = std::function<std::string(std::string& requeststr)>;static void* Execute(void* args) {ThreadData* td = static_cast<ThreadData*>(args);// 子线程结束后由系统自动回收资源,无需主线程调用 pthread_joinpthread_detach(pthread_self()); // 分离新线程,无需主线程回收std::string requeststr;ssize_t n = td->_sockfd->Recv(&requeststr);if (n > 0) {std::string responsestr = td->_self->_service(requeststr); // 执行回调td->_sockfd->Send(responsestr);                            // 发送响应}td->_sockfd->Close(); // 关闭连接套接字delete td;return nullptr;
}

整体代码 - TcpServer.hpp

#pragma once#include <iostream>
#include <memory>
#include <functional>
#include <sys/wait.h>#include "Thread.hpp"
#include "InetAddr.hpp"
#include "Socket.hpp"const int defaultprot = 8080;namespace TcpServerModule{using namespace SocketModule;using namespace LogModule;using service_t = std::function<std::string(std::string& requeststr)>;class TcpServer{public:TcpServer(service_t service, uint16_t port = defaultprot): _port(port), _listensock(std::make_shared<TcpSocket>()),_isrunning(false), _service(service){_listensock->BuildListenSocket(port);}void Loop(){_isrunning = true;while(_isrunning){InetAddr client;// 获取客户端连接SockPtr cli = _listensock->Accepter(&client);if(cli == nullptr) continue;LOG(LogLevel::DEBUG) << "get a new connection from " << client.AddrStr().c_str();// 获取成功pthread_t tid;// ThreadData 的头文件是 ThreadData* td = new ThreadData(cli, this, client);pthread_create(&tid, nullptr, Execute, td);  // 新线程分离}}// 线程函数参数对象class ThreadData{public:SockPtr _sockfd;TcpServer* _self;InetAddr _addr;public:ThreadData(SockPtr sockfd, TcpServer* self, const InetAddr& addr): _sockfd(sockfd), _self(self), _addr(addr){}};// 线程函数static void* Execute(void* args){ThreadData* td = static_cast<ThreadData*>(args);// 子线程结束后由系统自动回收资源,无需主线程调用 pthread_joinpthread_detach(pthread_self()); // 分离新线程,无需主线程回收std::string requeststr;ssize_t n = td->_sockfd->Recv(&requeststr);if(n > 0){std::string responsestr = td->_self->_service(requeststr);  // 执行回调td->_sockfd->Send(responsestr);  // 发送响应}td->_sockfd->Close();   // 关闭连接套接字delete td;return nullptr;}~TcpServer(){}private:uint16_t _port;SockPtr _listensock;bool _isrunning;service_t _service;};
}

2.1.2 Http.hpp

我们要实现的功能是 简单回显客户端的ip和端口号,所以需要一个类来实现这个功能

这个类不需要 构造析构 函数,只需要一个方法即可

class HttpServer{public:HttpServer(){}std::string handle(std::string req){std::cout << "------------------------------------" << std::endl;std::cout << req;return std::string();}~HttpServer(){}
};

2.1.3 TcpServer.cpp

我们现在已经不需要实现网络计算器功能了,所以不需要给 IOEcute 绑定一个计算器的功能只需要将上面 http 回显功能绑定在 TcpServer 对象上就行了

#include "TcpServer.hpp"
#include "Http.hpp"using namespace TcpServerModule;int main(int argc, char* argv[]){if(argc != 2){std::cerr << "Usage: " << argv[0] << " port" << std::endl;Die(1);}uint16_t port = std::stoi(argv[1]);HttpServer httpServer;std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(std::bind(&HttpServer::handle, &httpServer, std::placeholders::_1), port);tsvr->Loop();return 0;
}

2.2 模拟window客户端访问服务端

模拟测试window客户端访问我们的linux服务器的时候,要先将window的 Telnet 功能给下载好

具体路径:控制面板 -> 程序 -> 程序与功能 -> 启用或关闭windows功能 -> Telent功能 -> 重启电脑

在这里插入图片描述
然后我们使用 win+r 打开 cmd 命令,输入 telnet ip portip是你的服务器ip,port是你打开服务端时设置的端口号

在这里插入图片描述

2.3 模拟通过浏览器访问

通过在浏览器网址中输入相应的服务器 ip 和 端口号,即可访问

在这里插入图片描述

我们还可以更改 httpserver 中 handle 的处理方法,令这个网址在打开后,能够回显一串字符串 hello linux,hello net!

class HttpServer{public:HttpServer(){}std::string handle(std::string req){std::cout << "------------------------------------" << std::endl;std::cout << req;// return std::string();std::string responsestr = "HTTP/1.1 200 OK\r\n";responsestr += "Content-Type: text/html\r\n";responsestr += "\r\n";responsestr += "<html><h1>hello linux,hello net!<h2></html>";return responsestr;}~HttpServer(){}
};

在这里插入图片描述

🏳️‍🌈三、HTTP 协议请求与响应格式

2.1 Http 请求格式

这就是一段 http 请求报文
在这里插入图片描述

  • 首行: [方法] + [url] + [版本]
  • Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\r\n 分隔;遇到空行表示 Header 部分结束
  • Body: 空行后面的内容都是 Body. Body 允许为空字符串. 如果 Body 存在, 则在Header 中会有一个 Content-Length 属性来标识 Body 的长度;

在这里插入图片描述

2.2 Http 响应格式

在这里插入图片描述

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

在这里插入图片描述

基本的应答格式

在这里插入图片描述

🏳️‍🌈四、Http方法

在这里插入图片描述

4.1 Http 常用方法

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

  1. GET 方法(重点)
    用途:用于请求 URL 指定的资源。
    示例:GET /index.html HTTP/1.1
    特性:指定资源经服务器端解析后返回响应内容。

  2. POST 方法(重点)
    用途:用于传输实体的主体,通常用于提交表单数据。
    示例:POST /submit.cgi HTTP/1.1
    特性:可以发送大量的数据给服务器,并且数据包含在请求体中。

  3. PUT 方法(不常用)
    用途:用于传输文件,将请求报文主体中的文件保存到请求 URL 指定的位置。
    示例:PUT /example.html HTTP/1.1
    特性:不太常用,但在某些情况下,如 RESTful API 中,用于更新资源。

  4. HEAD 方法
    用途:与 GET 方法类似,但不返回报文主体部分,仅返回响应头。
    示例:HEAD /index.html HTTP/1.1
    特性:用于确认 URL 的有效性及资源更新的日期时间等。

  5. DELETE 方法(不常用)
    用途:用于删除文件,是 PUT 的相反方法。
    示例:DELETE /example.html HTTP/1.1
    特性:按请求 URL 删除指定的资源。

  6. OPTIONS 方法
    用途:用于查询针对请求 URL 指定的资源支持的方法。
    示例:OPTIONS * HTTP/1.1
    特性:返回允许的方法,如 GET、POST 等。

4.2 HTTP 的状态码

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

在这里插入图片描述

4.3 HTTP 常见 Header

Content-Type: 数据类型(text/html 等)
Content-Length: Body 的长度
Host: 客户端告知服务器, 所请求的资源是在哪个主机的哪个端口上;
User-Agent: 声明用户的操作系统和浏览器版本信息;
referer: 当前页面是从哪个页面跳转过来的;
Location: 搭配 3xx 状态码使用, 告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;


👥总结

本篇博文对 【Linux网络】HTTP协议全解析 - 从请求响应到方法与Header 做了一个较为详细的介绍,不知道对你有没有帮助呢

觉得博主写得还不错的三连支持下吧!会继续努力的~

http://www.xdnf.cn/news/2103.html

相关文章:

  • SpringBoot UserAgentUtils获取用户浏览器 操作系统设备统计 信息统计 日志入库
  • 从基础到实战的量化交易全流程学习:1.1 量化交易本质与行业生态
  • C++---类和对象(二)
  • VO包装类和实体类分别是什么?区别是什么?
  • C++学习笔记(四十)——STL之归约算法
  • 深入探究 MySQL 架构:从查询到硬件
  • Apache NetBeans 25 发布
  • 任务管理系统,Java+Vue,含源码与文档,科学规划任务节点,全程督办保障项目落地提效
  • priority_queue的学习
  • GoFly快速开发框架新增UI素材库-帮助开发者快速开发管理后台UI基于ArcoDesign框架开发
  • 服务器传输数据存储数据建议 传输慢的原因
  • 文本预处理(NLTK)
  • 图像处理——边缘检测
  • 【C++11】Lambda表达式
  • 区块链实战:Hyperledger Fabric多节点网络部署与高性能业务链码
  • 【运维】Windows 与 Linux 中实时查看日志的命令对比详解(tail -f)
  • 二叉搜索树的实现与应用场景
  • 指标监控:Prometheus 结合 Grafana,监控redis、mysql、springboot程序等等
  • 3:QT联合HALCON编程—海康相机SDK二次程序开发
  • 深入详解人工智能数学基础——微积分中拉格朗日乘数法在GAN训练中的应用
  • python调用ffmpeg对截取视频片段,可批量处理
  • 写了一个关于SpringAop记录用户操作的功能
  • A. Ambitious Kid
  • MySQL 联合查询教程
  • 使用PyTorch实现简单图像识别(基于MNIST手写数字数据集)的完整代码示例,包含数据加载、模型定义、训练和预测全流程
  • 深度探索:DeepSeek赋能WPS图表绘制
  • Docker化HBase排错实录:从Master hflush启动失败到Snappy算法未支持解决
  • Oracle官宣 MySQL+APEX+AI三认证限时免费
  • 使用 AFL++ 对 IoT 二进制文件进行模糊测试 - 第二部分
  • 基于 Requests 与 Ollama 的本地大模型交互全栈实践指南