应用层协议 --- 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 响应
首先我们来分析一下在应用层数据需要怎么处理:

- 首先,本地将请求序列化发送给服务端特定端口
- 服务端接收请求数据并反序列化,处理后得到相应的响应数据
- 服务端将响应数据序列化发送给客户端特定端口
- 客户端接受响应数据并反序列化,得到结果
结果分析,看起来我们需要完成请求数据的序列化和反序列化,响应数据的序列化和反序列化。但是其实 请求数据的序列化和响应数据反序列化 浏览器已经帮我们做了!当你访问一个 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
序言 在上一篇文章中,我们在应用层实现了一个非常简单的自定义协议,我们在我们报文的首部添加了报文的长度并且使用特定的符号分割。但是想做一个成熟,完善的协议是不简单的,今天我们就一起看看我们每天都会用到的 HTTP协议 。 UR…...
网卡Network Interface Card
文章目录 网卡(Network Interface Card,简称NIC)是一种计算机硬件设备,用于将计算机连接到计算机网络,使计算机能够进行数据通信。它是计算机与外部网络(如局域网、互联网)之间的接口࿰…...
9.1 Linux_I/O_基本知识
文件类型 一切I/O皆文件,文件就是存放在磁盘上面的有序数据的集合。 文件类型: 常规文件 r :就是普通文件目录文件 d :就是目录,是一个索引字符设备文件 c :键盘、鼠标块设备文件 b :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项目----详细步骤配置,传送门:http://t.csdnimg.cn/RsOs7 src:放class文件 web:放html文件 out:运行过后产生的文件 一创建一个新的web项目(配置好了后): 在src创建一个文件…...
jQuery——jQuery的2把利器
1、jQuery 核心函数 ① 简称:jQuery 函数,即为 $ 或者 jQuery ② jQuery 库向外直接暴露的是 $ 或者 jQuery ③ 引入 jQuery 库后,直接使用 $ 即可 当函数用:$(xxx) 当对象用:$.xxx&#x…...
Day29笔记-Python操作pdfPython发送邮件
一、Python操作PDF【了解】 1.pdf 简介 PDF是Portable Document Format的缩写,这类文件通常使用.pdf作为其扩展名。在日常开发工作中,最容易遇到的就是从PDF中读取文本内容以及用已有的内容生成PDF文档这两个任务。 在Python中,可以使用名为P…...
Seata分布式事务实践
理论篇 什么是事务 关于事务我们一定会想到下面这四大特性: 原子性:所有操作要么全都完成,要么全都失败。 一致性: 保证数据库中的完整性约束和声明性约束。 隔离性:对统一资源的操作不会同时发生的。 持久性:对事务完成的操作最终会持久化到数据库中。 理解&…...
数字IC设计\FPGA 职位经典笔试面试整理--基础篇2
1. 卡诺图 逻辑函数表达式可以使用其最小项相加来表示,用所有的最小项可以转换为卡诺图进行逻辑项化简 卡诺图讲解资料1 卡诺图讲解资料2 卡诺图讲解资料3 最小项的定义 一个函数的某个乘积项包含了函数的全部变量,其中每个变量都以原变量或反变量的形…...
(务必收藏)推荐市面上8款AI自动写文献综述的网站
在当前的学术研究和论文写作中,AI技术的应用已经变得越来越普遍。特别是在文献综述这一环节,AI工具能够显著提高效率并减少人工劳动。以下是市面上8款推荐的AI自动写文献综述的网站: 一、千笔-AIPassPaper 是一款备受好评的AI论文写作平台&…...
【python】运算符
学习目标 了解 Python 中常见 算术(数学)运算符赋值运算符 算术(数学)运算符 a 是 10,b 是 20 运算符描述实例加两个对象相加 a b 输出结果 30-减得到负数或是一个数减去另一个数 a - b 输出结果 -10*乘两个数相…...
C++深入学习string类成员函数(1):默认与迭代
引言 在 C 编程中,std::string 类是处理字符串的核心工具之一。作为一个动态管理字符数组的类,它不仅提供了丰富的功能,还通过高效的内存管理和操作接口,极大地方便了字符串操作。通过深入探讨 std::string 的各类成员函数&#…...
DataGrip远程连接Hive
学会用datagrip远程操作hive 连接前提条件: 注意: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之信息收集和扫描 在本文中,我们将学习以下内容 使用Metasploit被动收集信息 使用Metasploit主动收集信息 使用Nmap进行端口扫描 使用db_nmap方式进行端口扫描 使用ARP进行主机发现 UDP服务探测 SMB扫描和枚举 SSH版本扫描 FTP扫描 SMTP枚举 …...
基于Pytorch框架的深度学习MODNet网络精细人像分割系统源码
第一步:准备数据 人像精细分割数据,可分割出头发丝,为PPM-100开源数据 第二步:搭建模型 MODNet网络结构如图所示,主要包含3个部分:semantic estimation(S分支)、detail prediction…...
Go语言中的并发编程
Go语言中的并发编程Go语言中的并发编程主要依赖于两个核心概念:goroutine 和 channel。1. Goroutinegoroutine 的特点结束 goroutine2. Channel创建 Channel发送和接收数据Channel 的类型使用 select 语句简单的多个 goroutine使用 WaitGroup 等待所有 goroutine 完…...
python学习笔记(3)——控制语句
控制语句 我们在前面学习的过程中,都是很短的示例代码,没有进行复杂的操作。现在,我们将开始学习流程控制语句。 前面学习的变量、数据类型(整数、浮点数、布尔)、序列(字符串、列表、元组、字 典、集合&am…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
在 Spring Boot 中使用 JSP
jsp? 好多年没用了。重新整一下 还费了点时间,记录一下。 项目结构: pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...
MyBatis中关于缓存的理解
MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
性能优化中,多面体模型基本原理
1)多面体编译技术是一种基于多面体模型的程序分析和优化技术,它将程序 中的语句实例、访问关系、依赖关系和调度等信息映射到多维空间中的几何对 象,通过对这些几何对象进行几何操作和线性代数计算来进行程序的分析和优 化。 其中࿰…...
React、Git、计网、发展趋势等内容——前端面试宝典(字节、小红书和美团)
React React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么,Fiber架构,面试向面试官介绍,详细解释 用户: React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么,Fiber架构,面试向面试官介绍&#x…...
