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

应用层协议 --- HTTP

序言

 在上一篇文章中,我们在应用层实现了一个非常简单的自定义协议,我们在我们报文的首部添加了报文的长度并且使用特定的符号分割。但是想做一个成熟,完善的协议是不简单的,今天我们就一起看看我们每天都会用到的 HTTP协议


URL

1.再识 URL

 刚接触电脑时我们肯定就会了解到 URL,我们一般称他为 网址,我们利用网址来定位网络上的特定资源。但是现在我们开始接触计网了,还应该认识他的本质了。
 在之前的内容中我们知道,所谓网络通信不过就是 物理距离增加后的 进程间通信。想要和网络上的某个设备的进程进行通信,我们需要知道该设备的 IP 地址和端口号IP地址 用于将数据发送到该设备上,端口号 用于将数据发送到指定进程。
 所以我们可以合理的推测 URL 的背后运行逻辑也是这样,但是我们一般的网址都是:

https://www.baidu.com/

没有你说的 IP,端口 呀?这是因为我们还需要 DNS,网址中的域名部分通过 DNS 系统被解析成 IP 地址。DNS 是一个分布式数据库,负责将人类可读的域名转换成机器可读的 IP 地址。
 这样做的原因是 网址提供了一种更加用户友好的方式来定位和访问这些资源。通过域名系统和默认的端口号约定,用户可以在不知道具体IP地址和端口号的情况下,轻松地访问他们想要的网络资源。

2. URL 的组成

 现在我使用百度的搜索引擎输出一个 你好URL 生成如下:
在这里插入图片描述
输出一个简单的 你好 竟然这么长,我们来层次的划分理解一下:

  • 协议部分指定了用于访问资源的应用层协议,如 HTTP、HTTPS、FTP
  • 域名部分代表了资源所在的主机或服务器的名称
  • 路径部分指定了服务器上资源的具体位置,帮助服务器定位到用户请求的具体资源
  • 参数部分用于向服务器传递额外的信息,以便服务器根据信息返回更精确的结果

在这里重点介绍一下 路径部分,当我们只是输入一个域名时我们可以在后面加上具体要访问的资源的路径,但是如果我们没有加上的话,他会自动跟一个 \。咦?这不是根目录吗?不是的,服务端接收后会处理你的路径,方法各有不同,但是常见的是将 \ 替换为他首页的页面路径,就拿百度举例:
在这里插入图片描述


HTTP 协议

1. 什么是 HTTP

 在互联网世界中,HTTP(HyperTextTransferProtocol,超文本传输协议)是一个至关重要的协议。它定义了 客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如 HTML 文档)。经过前面的的铺垫学习,我们知道了只要是协议,双方就达成了一定的约定!
 在这里还需要注意重要的一点是,HTTP 的底层是基于 TCP 进行数据传输的!

2. HTTP 的请求与响应

2.1 请求报头

 现在我们做一个简单的试验,我们在云服务器上运行我们的服务端程序,并在本地的浏览器上使用 IP + 端口号 的形式访问,可以看到服务端输出:
在这里插入图片描述
很奇怪,我们并没有发送任何的内容,这是哪里来的呀?大家别忘了,浏览器在应用层,发送信息是会对报文增添报头,即使报文为空!这里输出的内容,就是 HTTP 协议约定好的报头!!!

 现在我们来看一下标准格式的请求头:
在这里插入图片描述

我们来了解一下请求行的作用:

  • 请求方法
    GET: 请求指定的资源,我们用的最多的方式
    POST:向服务器提交数据,比如登陆账号信息,会将具体的信息放在正文中
  • URL:这指定了请求的资源的路径,前面介绍过
  • HTTP版本:指定了客户端使用的 HTTP 协议版本,告诉服务器客户端能够理解的协议特性

请求报头数量是非常多的,并且很多都是需要特定的使用场景,我们只是介绍常用的报头:

  • Host: 指定请求的服务器的域名和端口号
  • User-Agent: 包含了发出请求的用户代理软件信息,通常是浏览器
  • Accept: 告诉服务器可以发送哪些媒体类型的内容
  • Content-Length: 请求体的长度
  • Cookie:缓存部分用户信息

 在这里可能需要阐明一点,如果你的请求方式为 GET,也是可以传递数据的。咦?不应该使用 POST吗?两个都行!比如搜索引擎,我们需要向输入框内输入搜索查询内容吧,我们的输入的内容就会以参数的格式加在 URL 后面。所以只是两者的方式不同,前者是将传递数据放在正文中,后者是放在 URL 中。
Cookie 非常重要,在后面会专门写一篇文章来进行说明,今天重要的是大体介绍 HTTP 的内容。

2.2 响应报头

 有了请求报文,现在我们再获取一下响应报文(在这里并没有找到一个很好抓包的方法,使用 AI 生成了一个效果一样的,嘻嘻):
在这里插入图片描述

响应报文的标准格式如下:
在这里插入图片描述
HTTP版本 就不多阐述了,我们重点其他内容,首先是状态码和状态码阐述:
在这里插入图片描述
一共包含 5 类,每一类的作用都大不相同,我们介绍最常见的状态码:

  • 200 OK:请求已成功,请求所希望的响应头或数据体将随此响应返回
  • 404 Not Found:服务器无法找到请求的资源。在浏览器中,这意味着 URL 输入错误或请求的页面已经被移除或不存在
  • 403 Forbidden:服务器理解请求,但拒绝执行它,通常都是权限不够
  • 302 Found (Redirect):请求的资源临时移动到了另一个 URI。客户端应该使用 GET 方法访问新的 URI ,原始请求的方法可能不再适用
  • 504 Gateway Timeout:作为网关或代理的服务器在等待上游服务器的响应时超时

原来这就是当我们搜索出错时弹出来的状态码的意义呀!最后便是我们的报头数据了:

  • Content-Type:指示响应主体的数据类型
  • Content-Length:指示响应主体的长度,以字节为单位
  • Date:指示响应生成的日期和时间

实现 HTTP 响应

 首先我们来分析一下在应用层数据需要怎么处理:
在这里插入图片描述

  1. 首先,本地将请求序列化发送给服务端特定端口
  2. 服务端接收请求数据并反序列化,处理后得到相应的响应数据
  3. 服务端将响应数据序列化发送给客户端特定端口
  4. 客户端接受响应数据并反序列化,得到结果

结果分析,看起来我们需要完成请求数据的序列化和反序列化,响应数据的序列化和反序列化。但是其实 请求数据的序列化和响应数据反序列化 浏览器已经帮我们做了!当你访问一个 URL 时其实已经将请求数据序列化并发送了!根据你的搜索呈现相应的结果不就是响应数据的反序列化吗?

 明白了这些,咋们直接开敲,首先肯定是构建 TCP注意:HTTP协议的底层使用的是 TCP 协议,如果你使用 UDP 是不能正常沟通的!!!) 的创建套接字文件:

// 创建套接字文件
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{perror("socket:");exit(1);
}
std::cout << "Successful create sockfd..." << std::endl;

 之后便是绑定:

 // 绑定struct sockaddr_in Address;Address.sin_family = AF_INET;Address.sin_addr.s_addr = INADDR_ANY;Address.sin_port = htons(PORT);int n = bind(sockfd, (struct sockaddr*)&Address, sizeof(Address));if(n < 0){perror("bind::");exit(1);}std::cout << "Successful bind..." << std::endl;

再者就是监听和接受连接:

// 监听
n = listen(sockfd, 3);
if(n < 0)
{perror("listen:");exit(1);
}
std::cout << "Successful listening..." << std::endl;// 等待接收连接
struct sockaddr_in ClientAddress;
socklen_t len = sizeof(ClientAddress);
int newfd = accept(sockfd,  (struct sockaddr*)&ClientAddress, &len);
if(newfd < 0)
{perror("accept:");exit(1);
}
std::cout << "Successful accept..." << std::endl;

这都是几乎比较固定的步骤!咋们对特定的业务只需要对数据处理模块进行特定的设计,现在我想要返回一个类似于网页的界面,就简单一下让人工智能帮咋们设计一下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>你好</title>
<style>@keyframes bounce {0%, 20%, 50%, 80%, 100% {transform: translateY(0);}40% {transform: translateY(-30px);}60% {transform: translateY(-15px);}}.bounce-text {font-size: 24px;animation: bounce 2s infinite;}
</style>
</head>
<body><div class="bounce-text">你好</div></body>
</html>

 现在当我们和客户端顺利连接时,咋们就按照协议的要求发送该内容:

std::string Content = GetIndex();
while(true)
{std::string response;response += "HTTP/1.0 200 OK\n";response += "Content-Length:" + std::to_string(Content.size()) + '\n';response += '\n'+ Content;send(newfd, response.c_str(), response.size(), 0);
}

我们简单的添加了状态行和响应报头最后是我们的上述 html 的内容,最后看一下效果:
在这里插入图片描述
成功啦,也不难是吧!


总结

 在这篇文章中我们简单认识了 HTTP 协议的组成,并且已经简单的实现了浏览器访问云服务器,返回相应数据的功能,希望大家有所收获!

相关文章:

应用层协议 --- HTTP

序言 在上一篇文章中&#xff0c;我们在应用层实现了一个非常简单的自定义协议&#xff0c;我们在我们报文的首部添加了报文的长度并且使用特定的符号分割。但是想做一个成熟&#xff0c;完善的协议是不简单的&#xff0c;今天我们就一起看看我们每天都会用到的 HTTP协议 。 UR…...

网卡Network Interface Card

文章目录 网卡&#xff08;Network Interface Card&#xff0c;简称NIC&#xff09;是一种计算机硬件设备&#xff0c;用于将计算机连接到计算机网络&#xff0c;使计算机能够进行数据通信。它是计算机与外部网络&#xff08;如局域网、互联网&#xff09;之间的接口&#xff0…...

9.1 Linux_I/O_基本知识

文件类型 一切I/O皆文件&#xff0c;文件就是存放在磁盘上面的有序数据的集合。 文件类型&#xff1a; 常规文件 r &#xff1a;就是普通文件目录文件 d &#xff1a;就是目录&#xff0c;是一个索引字符设备文件 c &#xff1a;键盘、鼠标块设备文件 b &#xff1a;U盘、磁…...

[Java]一、面向对象核心编程思想

G:\Java\1.JavaSE 1. 继承 1.1 继承的概述 重点内容:1.知道继承的好处2.会使用继承3.知道继承之后成员变量以及成员方法的访问特点4.会方法的重写,以及知道方法重写的使用场景5.会使用this关键字调用当前对象中的成员6.会使用super关键字调用父类中的成员7.会定义抽象方法以…...

科研绘图系列:R语言多个AUC曲线图(multiple AUC curves)

文章目录 介绍加载R包导入数据数据预处理画图输出结果组图系统信息介绍 多个ROC曲线在同一张图上可以直观地展示和比较不同模型或方法的性能。这种图通常被称为ROC曲线图,它通过比较不同模型的ROC曲线下的面积(AUC)大小来比较模型的优劣。AUC值越大,模型的诊断或预测效果越…...

JavaWeb--纯小白笔记06:使用Idea创建Web项目,Servlet生命周期,注解,中文乱码解决

使用Idea创建一个web项目----详细步骤配置&#xff0c;传送门&#xff1a;http://t.csdnimg.cn/RsOs7 src&#xff1a;放class文件 web&#xff1a;放html文件 out&#xff1a;运行过后产生的文件 一创建一个新的web项目(配置好了后)&#xff1a; 在src创建一个文件…...

jQuery——jQuery的2把利器

1、jQuery 核心函数 ① 简称&#xff1a;jQuery 函数&#xff0c;即为 $ 或者 jQuery ② jQuery 库向外直接暴露的是 $ 或者 jQuery ③ 引入 jQuery 库后&#xff0c;直接使用 $ 即可 当函数用&#xff1a;$&#xff08;xxx&#xff09; 当对象用&#xff1a;$.xxx&#x…...

Day29笔记-Python操作pdfPython发送邮件

一、Python操作PDF【了解】 1.pdf 简介 PDF是Portable Document Format的缩写&#xff0c;这类文件通常使用.pdf作为其扩展名。在日常开发工作中&#xff0c;最容易遇到的就是从PDF中读取文本内容以及用已有的内容生成PDF文档这两个任务。 在Python中&#xff0c;可以使用名为P…...

Seata分布式事务实践

理论篇 什么是事务 关于事务我们一定会想到下面这四大特性: 原子性:所有操作要么全都完成&#xff0c;要么全都失败。 一致性: 保证数据库中的完整性约束和声明性约束。 隔离性:对统一资源的操作不会同时发生的。 持久性:对事务完成的操作最终会持久化到数据库中。 理解&…...

数字IC设计\FPGA 职位经典笔试面试整理--基础篇2

1. 卡诺图 逻辑函数表达式可以使用其最小项相加来表示&#xff0c;用所有的最小项可以转换为卡诺图进行逻辑项化简 卡诺图讲解资料1 卡诺图讲解资料2 卡诺图讲解资料3 最小项的定义 一个函数的某个乘积项包含了函数的全部变量&#xff0c;其中每个变量都以原变量或反变量的形…...

(务必收藏)推荐市面上8款AI自动写文献综述的网站

在当前的学术研究和论文写作中&#xff0c;AI技术的应用已经变得越来越普遍。特别是在文献综述这一环节&#xff0c;AI工具能够显著提高效率并减少人工劳动。以下是市面上8款推荐的AI自动写文献综述的网站&#xff1a; 一、千笔-AIPassPaper 是一款备受好评的AI论文写作平台&…...

【python】运算符

学习目标 了解 Python 中常见 算术&#xff08;数学&#xff09;运算符赋值运算符 算术&#xff08;数学&#xff09;运算符 a 是 10&#xff0c;b 是 20 运算符描述实例加两个对象相加 a b 输出结果 30-减得到负数或是一个数减去另一个数 a - b 输出结果 -10*乘两个数相…...

C++深入学习string类成员函数(1):默认与迭代

引言 在 C 编程中&#xff0c;std::string 类是处理字符串的核心工具之一。作为一个动态管理字符数组的类&#xff0c;它不仅提供了丰富的功能&#xff0c;还通过高效的内存管理和操作接口&#xff0c;极大地方便了字符串操作。通过深入探讨 std::string 的各类成员函数&#…...

DataGrip远程连接Hive

学会用datagrip远程操作hive 连接前提条件&#xff1a; 注意&#xff1a;mysql是否是开启状态 启动hadoop集群 start-all.sh 1、启动hiveserver2服务 nohup hiveserver2 >> /usr/local/soft/hive-3.1.3/hiveserver2.log 2>&1 & 2、beeline连接 beelin…...

go 读取excel

一、安装依赖 go get github.com/tealeg/xlsx二、main.go package mainimport "fmt" import "github.com/tealeg/xlsx"type Student struct {Name stringSex string }func (student Student) show() {fmt.Printf("Name:%s Sex:%s\r\n", stude…...

Linux进阶系列(四)——awk、sed、端口管理、crontab

目录 1. 写在前面2. awk —— 强大的文本处理工具2.1 awk 概述2.2 awk 脚本结构2.3 awk 的内置变量2.4 awk 的高级用法2.5 awk实践 3. sed —— 流式文本编辑器3.1 sed 的基本语法3.2 sed 常用命令3.3 sed 的高级用法 4. Linux 端口管理4.1 端口的概念4.2 查看端口状态4.3 开放…...

利用Metasploit进行信息收集与扫描

Metasploit之信息收集和扫描 在本文中&#xff0c;我们将学习以下内容 使用Metasploit被动收集信息 使用Metasploit主动收集信息 使用Nmap进行端口扫描 使用db_nmap方式进行端口扫描 使用ARP进行主机发现 UDP服务探测 SMB扫描和枚举 SSH版本扫描 FTP扫描 SMTP枚举 …...

基于Pytorch框架的深度学习MODNet网络精细人像分割系统源码

第一步&#xff1a;准备数据 人像精细分割数据&#xff0c;可分割出头发丝&#xff0c;为PPM-100开源数据 第二步&#xff1a;搭建模型 MODNet网络结构如图所示&#xff0c;主要包含3个部分&#xff1a;semantic estimation&#xff08;S分支&#xff09;、detail prediction…...

Go语言中的并发编程

Go语言中的并发编程Go语言中的并发编程主要依赖于两个核心概念&#xff1a;goroutine 和 channel。1. Goroutinegoroutine 的特点结束 goroutine2. Channel创建 Channel发送和接收数据Channel 的类型使用 select 语句简单的多个 goroutine使用 WaitGroup 等待所有 goroutine 完…...

python学习笔记(3)——控制语句

控制语句 我们在前面学习的过程中&#xff0c;都是很短的示例代码&#xff0c;没有进行复杂的操作。现在&#xff0c;我们将开始学习流程控制语句。 前面学习的变量、数据类型&#xff08;整数、浮点数、布尔&#xff09;、序列&#xff08;字符串、列表、元组、字 典、集合&am…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...