[ 网络 ] 应用层协议 —— HTTP协议
目录
1.HTTP协议
1.1URL
urlencode和urldecode
2. HTTP协议格式
HTTP请求
HTTP响应
3.告知服务器意图的HTTP方法
GET:获取资源
POST:传输实体主体
GET和POST的区别
使用Cookie的状态管理
4.返回结果的HTTP状态码
状态码告知从服务器端返回的请求结果
2XX成功
3XX重定向
4XX客户端错误
5XX服务器错误
5.HTTP的缺点
1.HTTP协议
应用层协议已经有大佬定义了一些现成的,有非常好用的应用层协议,我们可以直接参考使用。例如本篇所提到的HTTP(超文本传输协议)就是其中之一。
1.1URL
URL(统一资源定位符)就是我们俗称的"网址"

我们所常见到的网址:例如 https://www.baidu.com/ 是域名,这种字符串风格的域名,具有更好的字描述性。域名在解析时必须被转换成为IP地址,要访问网络服务,又必须具有port.
协议方案名和服务器端口号是强绑定的:
比如httpserver --- 80 ; httpsServer --- 443 ; sshd --- 22
HTTP协议的本质是要获得某种"资源",比如我们请求百度的官网时,我们所获取的资源是百度首页的网页信息。我们可以理解为HTTP是 获取网页资源的(视频,音乐等)。HTTP是向特定的服务器向特定端口申请特定的"资源"的,获取到本地进行展示或者某种展示的。而对应服务器上,你所要的资源所在的位置就是URL中带层次的文件路径。
实际上,上网的大部分行为,都在进行这进程间通信。既然是通信,就是获取信息和发送信息。所以我们对应到生活中,大部分的上网行为,无非两种:
- 把服务器上面的资源数据拿到本地(短视频,小说等等)
- 把本都的数据推送到服务器(搜索,注册,登录,下单等)
urlencode和urldecode
在URL中,像 / ? 等这样的字符已经被URL当做特殊意义理解了。因此这些字符不能随意出现。

比如:某个参数中需要带有这些特殊字符,就必须先对特殊字符进行转义。
转义规则:将需要转码的字符转为16进制,然后从右到做,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式。

我们可以看到 "C++" 中 "+"被转义成了 "%2B" 我们可以使用urlencode工具验证上述过程
UrlEncode编码/UrlDecode解码 | urldecode就是urlencode的逆过程。

2. HTTP协议格式
HTTP请求


- 首行:【方法】+【URL】+【版本】
- Header:请求的属性,冒号分割的键值对;每组属性之间使用\n分割;遇到空行表示Header部分结束
- Body:空行后面的内容都是Body.Body允许为空字符串.如果Body存在,则在Header中会有一个Content-Length字段用来表示Body的长度
常规情况下,HTTP(HTTPS)底层使用的传输层协议是TCP.
我们通过一段tcp套接字编程来查看HTTP请求格式
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>using namespace std;
int main()
{int listen_sock = socket(AF_INET,SOCK_STREAM,0);if(listen_sock < 0){std::cout<<"socket error" <<std::endl;return 1;}struct sockaddr_in local;memset(&local,0,sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(8082);local.sin_addr.s_addr = INADDR_ANY;if(bind(listen_sock,(struct sockaddr*)&local, sizeof(local))<0){std::cout<<"bind error" << std::endl;return 2;}if(listen(listen_sock,5) < 0){std::cout<<"listen error" << std::endl;return 3;}struct sockaddr_in peer;for(;;){socklen_t len = sizeof(peer);int sock = accept(listen_sock,(struct sockaddr*)&peer,&len);if(sock < 0){std::cout<<"accept error "<<std::endl;continue;}if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);std::cout<<"###################HTTP request begin####################"<<std::endl;std::cout<< buffer << std::endl;std::cout<<"###################HTTP request end####################"<<std::endl;exit(0);}close(sock);waitpid(-1,nullptr,0);}
}

我们在直接打印出请求的格式
第一部分 首行:请求方法 请求url HTTP协议的版本
常用的请求方法:GET和POST (后面详解)
刚刚我们请求的是 / . " / " 是Web根目录不是系统根目录。那我们也可以请求 /a/b/c/d.html 我们再次看看请求报文:



第二部分是一组Key:value的请求报头
请求报头是一堆Key: Value 请求属性,包括是否需要长链接,浏览器的编码类型,数据类型,我们想发送给服务器的相关信息等等.....通常存在多行,是一堆的Key: Value值

服务器端可以按行循环读取,一直读到\n (空行)就证明已经把报头读完了
第三部分:空行
是报头和有效载荷的分离符,为了就是将报头和有效载荷进行分离

前三部分都必须是按行方式陈列的

第四部分:请求正文(有效载荷) ——非必须 | 可以没有
根据我们的需求,有时候我们需要登录账号和密码,个人信息,音乐,视频等等一般都是用户的相关信息或者数据。
以上就是HTTP协议的请求(HTTP request)。
HTTP响应

- 首行: 【版本号】 + 【状态码】 + 【状态码解释】
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中.
HTTP响应也是由4部分组成,其中响应正文也是可以被省略的。客户端如何判断已经将response报头读取完毕呢,仍然是客户端可以循环按行读取,知道读取到空行。
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fstream>using namespace std;
int main()
{int listen_sock = socket(AF_INET,SOCK_STREAM,0);if(listen_sock < 0){std::cout<<"socket error" <<std::endl;return 1;}struct sockaddr_in local;memset(&local,0,sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(8083);local.sin_addr.s_addr = INADDR_ANY;if(bind(listen_sock,(struct sockaddr*)&local, sizeof(local))<0){std::cout<<"bind error" << std::endl;return 2;}if(listen(listen_sock,5) < 0){std::cout<<"listen error" << std::endl;return 3;}struct sockaddr_in peer;for(;;){socklen_t len = sizeof(peer);int sock = accept(listen_sock,(struct sockaddr*)&peer,&len);if(sock < 0){std::cout<<"accept error "<<std::endl;continue;}if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);// std::cout<<"###################HTTP request begin####################"<<std::endl;// std::cout<< buffer << std::endl;// std::cout<<"###################HTTP request end####################"<<std::endl;#define PAGE "./wwwroot/index.html"std::ifstream in(PAGE);if(in.is_open()){in.seekg(0,std::ios::end);size_t len = in.tellg();in.seekg(0,std::ios::beg);char *file = new char[len];in.read(file,len);in.close();std::string status_line = "http/1.0 200 OK\n";std::string response_header = "Content-Length: "+std::to_string(len);response_header+="\n";std::string blank = "\n";send(sock,status_line.c_str(),status_line.size(),0);send(sock,response_header.c_str(),response_header.size(),0);send(sock,blank.c_str(),blank.size(),0);send(sock,file,len,0);delete[] file;}close(sock);exit(0);}close(sock);waitpid(-1,nullptr,0);}
}

3.告知服务器意图的HTTP方法
在众多的HTTP方法中最常用的是GET和POST方法,因此在此我们对GET和POST进行详细了解

GET:获取资源
GET方法是用来请求访问已被URL识别的资源。指定的资源经服务器端解析后返回响应内容。

我们也可以使用Postman工具抓取HTTP请求

POST:传输实体主体
POST方法是用来传输实体的主体
虽然用GET方法也可以传输实体的主体,但是一般不用GET方法进行传输,而是用POST方法。虽然POST的功能和GET很相似,但是POST的主要目的并不是获取响应的主体内容。

GET和POST的区别
- GET方法可以带参,参数在URL " ?"的后面
- POST方法通过正文传参
- GET方法传参不私密
- POST方法因为通过正文传参,所以相对私密一些
GET通过url传参,POST通过正文传参,所以一般一些大的内容都是通过POST传参。
使用Cookie的状态管理
HTTP是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求管理。那么我们在日常上网的过程中,假设要求登录认证的Web页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转新页面的时候都要再次登录,或者每次请求报文中附加参数来管理登录状态。那么这对我们用户是非常不友好的,就相当于我们每次登录C站我们都要进行登录认证。因此Cookie技术就是通过在请求和响应报文中写入Cookie信息来控制客户端的状态。
Cookie会根据从服务器端发送的响应报文内的一个叫Set-Cookie的首部字段信息,通知客户端保存Cookie。当下次客户端再往服务器发送请求时,客户端会自动在请求报文中加入Cookie值后发送出去。服务器端发现过来的Cookie后,会检查究竟是从哪一个客户端的连接请求,然后对比服务器上的记录,最后得到之前的状态信息。
举例:我们用B站来进行举例。
我只要登录过B站之后,再之后再次登录B站时会自动登录我的账号, 点击网址左边的锁,就会看到Cookie,点进去就会看到当前页面下的Cookie信息,我们全部进行删除后点击完成,再次刷新该页面,就发现无法找到之前的登录信息了。登录后再次查询发现Cookie信息被重新填写上了。






4.返回结果的HTTP状态码
HTTP状态码负责表示客户端HTTP请求的返回结果,标记服务器端的处理是否正常,通知出现的错误等工作。
状态码告知从服务器端返回的请求结果
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求还是出现了错误。
状态码的类别

2XX成功
2XX的响应结果表明请求被正常处理了。
例如:
- 200 OK表示从客户端发来的请求在服务器端被正常处理了。
- 204 No Content 表示服务器接受的请求已成功处理,但在返回的响应报文中不含有实体的主体部分,也就是说请求处理成功但是没有资源可以返回。因此返回204响应后浏览器的显示页面不会发生更新。
3XX重定向
- 301 Moved Permanently 永久重定向。该状态码表示请求的资源已被分配了新的URL,以后应使用现在所指的URL。
- 302 Found 临时重定向。该状态码表示请求的资源已被分配了新的URL,希望用户本次能使用新的URL访问。
- 302和301状态码相似,但是302状态码代表的资源不是永久移动,只是临时性质的。换句话说,302的资源对应的URL将来还有可能发生变。
if(fork() == 0){if(fork() > 0) exit(0);close(listen_sock);char buffer[1024];recv(sock,buffer,sizeof(buffer),0);//重定向到腾讯网std::string response = "HTTP/1.1 301 Permanently Moved\r\n";response += "Location: https://www.qq.com/\r\n"; response += "\r\n";send(sock, response.c_str(), response.size(), 0);close(sock);exit(0);}
当服务器启动之后在浏览器输入ip:port后按下回车发现URL自动跳转到了腾讯网

4XX客户端错误
- 403 Forbidden 表示请求资源的访问被服务器拒绝了。服务器端没有必要给出拒绝的详细理由。
- 发生403的原因:未获得文件系统的访问授权,访问权限出现某些问题(从未授权的发送源IP地址试图访问)
- 404 Not Found 表示服务器上无法找到请求的资源。除此之外,也可能在服务器端拒绝请求且不想说明理由时使用。
5XX服务器错误
5XX的响应结果表名服务器本身发生错误
- 500 Internal Server Error 表示服务器端在执行请求时发生了错误。也可能是Web应用存在的Bug或某些临时的故障。
5.HTTP的缺点
HTTP主要有如下不足之处:
- 通信使用明文(不加密),内容可能会被窃听
- 不验证通信方的身份,因此有可能遭遇伪装
- 无法证明报文的完整性,所以有可能已经遭到篡改
因此解决如上三个不足之处正是HTTPS的主要功能,因此HTTPS = HTTP+加密+认证+完整性保护。具体3个功能的实现细节,将单独整理成一篇博客HTTPS
相关文章:
[ 网络 ] 应用层协议 —— HTTP协议
目录 1.HTTP协议 1.1URL urlencode和urldecode 2. HTTP协议格式 HTTP请求 HTTP响应 3.告知服务器意图的HTTP方法 GET:获取资源 POST:传输实体主体 GET和POST的区别 使用Cookie的状态管理 4.返回结果的HTTP状态码 状态码告知从服务器端返回的…...
Spring Boot 整合 Redisson 缓存性能客户端(2023-03-06)
Spring Boot 整合 Redisson 缓存 (官网) 介绍: Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, Sorte…...
【C和C++】输出100内能够被13整除的数,取模判断方法
目录 前言基础概念重温整除例子小知识点收尾前言 在软件行业已经有快十年,技术虽然一般般,但是足够应付和解决编程入门的相关问题! 都说十年磨一剑,积累到一定经验,是时候发挥自己的价值,给予入门的同行些许的帮助! 为什么要写收费专栏,其实原因很简单,时间就是金钱(…...
STC8单片机基于开源库读取DS18B20数据例程
STC8单片机基于开源库读取DS18B20数据例程 📍开源库FwLib_STC8 Github地址:https://github.com/IOsetting/FwLib_STC8📌STC官方STC8库函数资源:https://www.stcai.com/khs🎉本次利用FwLib_STC8库读取DS18B20,由于该开源库是基于VSCode编写,默认使用的是SDCC编译器,在…...
计算机专业毕业设计基于Spring Boot 学生在线考试系统
目录 一、学生端 1.1 登录 1.2 注册 1.3 学生首页 1.4 学生查看任务中心的试卷(已答卷/未答卷) 1.5 学生查看固定试卷以及开始做题 1.6 学生查看时段试卷以及开始做题 1.7 学生查看试卷中心 1.8 学生查看考试记录以及查看试卷 1.9 学生查看…...
【读书笔记】《深入浅出数据分析》第八章 启发法
目录一,什么是启发法?1,那什么是启发法?2,心理学上对启发法定义二,活动分析1,如何去分析活动效果呢?1.1 活动前期(活动前1-2周)1.2 活动中期1.3 活动结束一&a…...
英飞凌Tricore实战系列导读
本文框架 1.系列概述1.1 外设理论及应用介绍1.2 基于TC3xx的MCAL各外设配置开发1.3 基于TC3xx的Davinci工程开发1.4 项目中问题排查经验分享1.5 其他相关话题分享2. 目前已发布系列文章汇总1.系列概述 英飞凌TC3xx以其强大的性能,扩展性,存储及安全性能在汽车电子中扮演着越…...
做数据分析有前景吗?
当然有前景的。 每个行业都有发展前景,只是看你自身的技能情况或者关系人脉、软实力方面是否到位,不同的行业要求不一样。作为数据分析领域而言,属于IT行业,看的是你的专业技能;只要你技能过硬,就能在行业…...
Rust Web入门(六):服务器端web应用
本教程笔记来自 杨旭老师的 rust web 全栈教程,链接如下: https://www.bilibili.com/video/BV1RP4y1G7KF?p1&vd_source8595fbbf160cc11a0cc07cadacf22951 学习 Rust Web 需要学习 rust 的前置知识可以学习杨旭老师的另一门教程 https://www.bili…...
1.特定领域知识图谱知识融合方案(实体对齐):金融产业产业知识图谱-基于内容匹配和图模型的品牌知识链指
1 引言 供应链金融是一种围绕经营关系,以核心企业为依托,针对中小企业的新型金融服务。如何精准地还原企业间的经营关系,是供应链金融的关键所在。知识图谱是描绘实体间关系的网络结构,对于挖掘企业关系有重要意义。在真实场景中,仅有企业与用户的微观知识对于还原经营关系…...
前端基础语法合集
JS语法基础1-注释//单行注释/*......*/多行注释2-分号;用作分割javascript语句,可以省略。3-变量定义定义变量使用varvar a;//声明变量 var a100;//声明变量并赋值 var b,c;//声明多个变量 var d20;bd1;cb1;//一行多条语句要用;分割4-数据类型判断该变量…...
百亿补贴,京东的自卫反击战
“百亿补贴”这个词大家有没有很熟悉?大部分人应该是在看拼多多投放广告的时候,知道这个词的吧。而京东APP也于近日在升级11.6.2版本时,在更新日志中明确提到:“京东3.8节,百亿补贴上线”。至此,发酵数日的…...
融云入选中国信通院《高质量数字化转型产品及服务全景图》
企业数字化转型正在进入“深水区”。 3 月 3 日,“中国信息通信研究院(以下简称中国信通院)高质量数字化转型创新发展大会暨中国信通院‘铸基计划’年度峰会”在京召开,深度展示了中国信通院在数字化转型领域的工作成果ÿ…...
开源消息代理组件mosquitto
# ll total 556 -rw-r----- 1 sk sk 148417 Mar 6 14:59 libuv-1.44.2-1.el7.x86_64.rpm -rw-r----- 1 sk sk 120717 Mar 6 14:59 libwebsockets-3.0.1-2.el7.x86_64.rpm -rw-r----- 1 sk sk 293429 Mar 6 14:59 mosquitto-1.6.10-1.el7.x86_64.rpm 将用到的依赖上传到主机…...
vuex的五个属性及使用方法示例
一,Vuex简介 Vuex是Vue.js的状态管理库,它通过中心化的状态管理使得组件间的数据共享更加容易。 Vuex包含五个核心属性:state、getters、mutations、actions和modules。 Vuex是Vue.js的状态管理库,它提供了一种集中式存储管理应…...
9.SpringSecurity核心过滤器-SecurityContextPersistenceFilter
SpringSecurity核心过滤器-SecurityContextPersistenceFilter 一、SpringSecurity中的核心组件 在SpringSecurity中的jar分为4个,作用分别为 jar作用spring-security-coreSpringSecurity的核心jar包,认证和授权的核心代码都在这里面spring-security-co…...
23种设计模式-桥接模式
概念 桥接模式是一种结构型设计模式,它通过将抽象与其实现分离来解耦。它使用接口(抽象类)作为桥梁,将一个抽象类与其实现类的代码分别独立开来,从而使它们可以各自独立地变化。桥接模式的核心思想是“组合优于继承”…...
TCP PMTU 静态路由
HTTP协议 --- 超文本传输协议TCP --- 80端口超文本 --- 包含有超链接link和多媒体元素标记的文本TCP协议是一种面向连接的可靠性传输协议面向连接:数据在传输前,收发双方建立一条逻辑通道。可靠性确认机制:传输确认,每接受一个数据…...
Android动画——属性动画
在属性动画中,常用到的API有ValueAnimator,ObjectAnimator。ValueAnimator:时间引擎,负责计算各个帧的属性值,基本上其他属性动画都会直接或间接继承它;ObjectAnimator: ValueAnimator 的子类&a…...
华为OD机试真题Python实现【寻找连续区间】真题+解题思路+代码(20222023)
寻找连续区间 题目 给定一个含有N个正整数的数组, 求出有多少个连续区间(包括单个正整数), 它们的和大于等于x。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 第一行两个整数N x (0 < N <= 100000 ,0 <= x <=…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
