详解HTTP协议
迪丽瓦拉
2025-05-28 17:39:07
0

文章目录

  • 前言
  • 一、认识URL
    • urlencode和urldecode
  • 二、http协议格式
  • 三、http的请求方法
    • GET和POST的区别
  • 三、HTTP的状态码
    • 重定向
  • 四、HTTP常见的Header
    • cookie
    • session
    • Connection
  • 总结


前言

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


正文开始!

一、认识URL

在这里插入图片描述
在这里插入图片描述

但是在我们现在使用中,端口号大多都被省略了!

如下:

在这里插入图片描述

这是因为在使用确定协议的时候,一般显示的时候,会缺省端口号(有端口号被省略了).

所以,浏览器访问指定的URL的时候,浏览器必须给我们自动添加port;

浏览器如何得知,URL匹配的port是谁呢? 特定的众所周知的服务,端口号必须是确定的!!!

http->80
https->443
sshd->22

注意:
我们自己写的网络服务bind端口的时候,只能绑定[1024,n]范围内的端口号.

在这里插入图片描述
http就是获取网页资源的,视频,音频等的也都是文件!!!也就是向特定的服务器申请特定的"资源",然后获取到本地,进行展示和某种使用的!

如果client没有获取的时候,资源在哪里呢?—>远端的服务器!!!—>服务器都是Linux系统!—>这些资源都是文件!—>通过路径来访问文件!

urlencode和urldecode

像 / ? : 等这样的字符,已经被url当做特殊意义理解了.因此这些字符不能随意出现.

比如,某个参数中需要带有这些字符,就必须先对特殊字符进行转义.

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

例如:

在这里插入图片描述


在这里插入图片描述

“+“就被转义为”%2B”.
urldecode就是urlencode的逆过程.

urlencode工具!!!

二、http协议格式

在这里插入图片描述

任何协议的request or response:
报头+有效载荷

那么http如何保证自己的报头和有效载荷被全部读取呢?----无论是请求还是响应.

  1. 读取完整报头:按行读取,直到读取到空行!
  2. 你又如何保证,你能读取到完整的正文呢?(报头能读取完毕,请求或者响应属性中,"一定"要包含正文的长度!)

server.hpp

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define CRLF "\r\n"
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define HOME_PAGE "index.html" //首页字段
#define ROOT_PATH "wwwroot"string GetPath(string httpRequest)
{size_t pos = httpRequest.find(CRLF);if(pos == string::npos) return "";string requestLine = httpRequest.substr(0,pos);//GET /a/b/index.html http/1.0size_t first = requestLine.find(SPACE);if(first == string::npos) return "";size_t second = requestLine.rfind(SPACE);if(second == string::npos) return "";string path = requestLine.substr(first+SPACE_LEN,second-(first+SPACE_LEN));if(path.size()==1 && path[0]=='/') path+=HOME_PAGE;return path;}
string readFile(const string& recource)
{// int fd = open(recource.c_str(),O_RDONLY|O_APPEND,0666);ifstream in(recource);if(!in.is_open()) return "404";string content;string line;while(getline(in,line)){content += line;}in.close();return content;}void handlerHttpRequest(int sock)
{char buffer[10240];ssize_t s = read(sock,buffer,sizeof buffer);if(s>0){cout<
public:ServerTcp(uint16_t port, string ip = ""): _listenSock(-1), _port(port), _ip(ip){}~ServerTcp(){}public:void init(){// 1.创建socket_listenSock = socket(AF_INET, SOCK_STREAM, 0);if (_listenSock < 0){exit(1);}// 2.bind绑定// 2.1填充服务器struct sockaddr_in local; // 用户栈memset(&local, 0, sizeof local);local.sin_family = AF_INET;local.sin_port = htons(_port);_ip.empty() ? (local.sin_addr.s_addr = INADDR_ANY) : (inet_aton(_ip.c_str(), &local.sin_addr));// 2.2本地socket信息,写入_sock对应的内核区域if (bind(_listenSock, (const sockaddr *)&local, sizeof local) < 0){exit(2);}// 3.监听socket,为何要监听呢?tcp是面向连接的!if (listen(_listenSock, 5 /*后面再说*/) < 0){exit(3);}// 允许别人来连接你了}void loop(){while (true){struct sockaddr_in peer;socklen_t len = sizeof(peer);// 4.获取连接,accept的返回值是一个新的socket fd??// 4.1 _listenScok:监听&&获取新的连接--->sock// 4.2 serviceSock:给用户提供新的socket服务int serviceSock = accept(_listenSock, (struct sockaddr *)&peer, &len);if (serviceSock < 0){continue;}// //5.1 V1.1---多进程版本//爷爷进程pid_t id=fork();assert(id != -1);if(id==0){//爸爸进程close(_listenSock);//又进行了一次forkif(fork()>0) exit(0);//孙子进程--就没有爸爸进程了--孤儿进程--被系统领养了--回收问题就交给了系统来回收handlerHttpRequest(serviceSock);exit(0);}close(serviceSock);//爸爸进程直接终止,立马得到退出码,释放僵尸进程状态pid_t ret=waitpid(id,nullptr,0);//就用阻塞式等待(void)ret;}}private:int _listenSock;uint16_t _port;string _ip;
};

serverTcp.cc

#include"server.hpp"
static void Usage(string proc)
{cerr << "Usage\n\t" << proc << " port ip" << endl;cerr << "Example\n\t" << proc << " 8080  127.0.0.1\n"<< endl;
}// ./serverTcp local_port [local_ip]
int main(int argc, char *argv[])
{if (argc != 2 && argc != 3){Usage(argv[0]);exit(4);}uint16_t port = stoi(argv[1]);string ip;if (argc == 3){ip = argv[2];}ServerTcp svr(port, ip);svr.init();svr.loop();return 0;
}

在这里插入图片描述

在这里插入图片描述
备注:此处我使用了8080端口号启动了HTTP服务器,虽然HTTP服务器一般使用80端口!
但这只是一个通用的习惯.并不是说HTTP服务器就不能使用其他的端口号.

以上就是一个表单!
我们的网络行为无非有两种:

  1. 我想把远端的资源拿到你的本地:GET /index.html htpp/1.1
  2. 我们想把我们的属性字段提交给远端. GET or POST

用抓包软件进行抓包!
在这里插入图片描述

三、http的请求方法

方法说明支持的HTTP协议版本
GET获取资源1.0、1.1
POST传输实体主体1.0、1.1
PUT传输文件1.0、1.1
HEAD获得报文首部1.0、1.
DELETE删除文件1.0、1.1
OPTIONS询问支持的方法1.1
TRACE追踪路径1.1
CONNECT要求用隧道协议连接代理1.1
LINK建立和资源之间的联系1.0、1.1
UNLINE断开连接关系1.0、1.1

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

GET和POST的区别

在这里插入图片描述
区别:

  1. GET通过url传参
  2. POST通过正文传参
  3. GET方法传参不私密
  4. POST方法通过正文传参,所以相对私密一些.
  5. GET通过url传参,POST通过正文传参,所以一般一些比较大的内容都是通过POST方式传参的!

三、HTTP的状态码

类别原因短语
1XXInformational(信息状态码)接受的请求正在处理
2XXSuccess(成功状态码)请求正常处理完毕
3XXRedirection(重定向状态码)需要进行附加操作以完成请求
4XXClient Error(客服端错误状态码)服务器无法处理请求
5XXServer Error(服务器错误状态码)服务器处理请求出错

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

重定向

301:永久重定向
302:临时重定向
在这里插入图片描述

四、HTTP常见的Header

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

在这里插入图片描述

cookie

http协议特点之一:无状态
举个栗子:比如你刚才访问一个网页之后,http是不会帮你做记录的,也就是说http不知道你之前访问的是那个网页.

那么用户需要一个功能:会话保持.

一旦登陆,会有各种会话保持的策略.

使用B站举个栗子:

在这里插入图片描述
在这里插入图片描述
删除这些字段以后

在这里插入图片描述
刷新一下页面

在这里插入图片描述

这个网页就不认识这个用户了!

cookie:存储用户名&&密码
以后发起http请求访问该网站就会自动携带cookie文件中的内容.

在这里插入图片描述

在这里插入图片描述
cookie:浏览器维护的文件.真正的存在磁盘&&内存级文件.

注意: cookie的安全问题,比如中间人可能通过某种手段(植入病毒等)获取到了我们的cookie文件中的用户名和密码,获取到我们的信息,那么就可以以我们的身份访问网站了???

接下来引入session字段,解决这个问题!

session

在这里插入图片描述

Connection

Connection:keep-alive 长连接
用户所看到的的完整的页面内容–背后可能是无数次http请求
http底层主流采用的就是tcp协议!
一个tcp链接会有多个http请求!(根据请求报头中的Content-Length字段读取多个请求!)

http协议是无连接的!


总结

(本章完!)

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...