超详细的HTTP协议
2021/6/27 0:00:30
本文主要是介绍超详细的HTTP协议,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
文章目录
- HTTP协议是什么?
- HTTP协议格式
- 请求行
- 请求方法
- URL
- 协议版本
- HTTP0.9
- HTTP1.0
- HTTP1.1
- 长连接
- 管道机制
- 分块传输
- HTTP2.0
- 响应行
- 头部
- Cookie与Session
- Cookie
- Session
- Cookie与Session的区别
- 空行
- 正文
- 简单的http服务器的搭建
- 输入URL后发生了什么
HTTP协议是什么?
HTTP:超文本传输协议。HTTP 协议和 TCP/IP 协议族内的其他众多的协议相同, 用于客户端和服务器之间的通信。请求访问文本或图像等资源的一端称为客户端, 而提供资源响应的一端称为服务器端。
-
http是一个明文字符串传输协议
-
http在传输层基于tcp协议实现
-
http是一个简单的请求-响应协议
HTTP协议格式
首行:请求行,响应行
头部:对于请求或者响应或者正文的一些关键描述。由一个个键值对key:空格value
组成,每个键值对以\r\n
结尾
空行:\r\n
,间隔头部与正文
正文:客户端提交给服务端,或者服务端响应给客户端的数据
请求信息:
响应信息:
采用的工具是Fiddler。Fiddler是一个HTTP调试抓包工具,它能记录所有客户端和服务器的http和https请求。
请求行
请求行:请求方法空格
URL空格
协议版本\r\n
请求方法
GET:从服务端获取实体资源,请求没有正文,但是也可以提交数据,提交的数据没有在正文中而是在URL中。
GET方法缺陷:
GET提交数据不安全。提交的数据在URL中,URL可见,所以不安全。
URL长度有限制。在早期,长度限制是1KB,现在长度限制是4KB或者8KB。
HEAD: 功能与GET类似。GET在服务器响应时,会有正文部分。而HEAD在服务器响应时,没有正文部分。
POST: 向服务端提交数据,请求有正文,数据放在正文中。
其他请求方法:
URL
URL:统一资源定位符,用于定位网络中某个主机上的某个资源。也就是我们所说的网址。
URL组成:协议名称://用户民:密码@域名:端口/资源路径?查询字符串#标识
用户名与密码容易暴露信息,不安全,所以现在的URL中不写用户名和密码。http的默认使用80端口,https默认使用443端口。
域名: 服务器别名。最终访问服务器需要经过域名解析得到服务器IP。一个URL中,也可以直接使用IP地址作为域名使用。
/资源路径: 请求这个路径下的资源。这个路径是一个相对根目录。
查询字符串: 提交给服务器的数据。由一个个key=value形式键值对组成,键值对之间以&符号间隔。
用户请求的资源路径,或者查询字符串中存在特殊字符,则有可能与url中的特殊字符冲突,所以采用urlencode编码方式进行编码。
urlencode编码:将特殊字符每个字节转换为16进制数字字符,并前缀%
urldecode解码:遇到%
则认为紧随其后的两个字符进行了编码,将这两个字符转化为数字。
示例:
根据上图所示,我们要查询的数据是c++,而’+'的ASCII码值是43,转换为16进制就是2B,并且前缀%,就是url中的数据c%2B%2B。
协议版本
HTTP协议总共经过了0.9、1.0、1.1、2.0版本。
HTTP0.9
最早期的版本,只支持GET方法,只支持超文本数据传输(仅能请求访问HTML格式的资源)。
HTTP1.0
在0.9版本上做了改进,规范了http协议格式,增加了请求方式POST和HEAD;不再局限于0.9版本的HTML格式,支持各种多媒体资源传输;支持简单的缓存机制,就是当客户端在规定时间内访问同一网站,直接访问cache即可。
但是1.0版本的工作方式是每次TCP连接只能发送一个请求,当服务器响应后就会关闭这次连接,下一个请求需要再次建立TCP连接。这就是所谓的短连接。TCP连接的新建成本很高,因为需要客户端和服务器三次握手,并且开始时发送速率较慢。所以HTTP1.0版本,性能较差。随着网页需要加载的资源越来越多,这个问题就愈发突出。
HTTP1.1
更多的是对1.0版本进行性能的优化,支持了更多请求方法以及特性。比如说:支持长连接、更加完善的缓存控制、分块传输、管道机制等。
长连接
Connection:用于控制长连接的打开关闭状态
keep-alive/close
1.1版本的最大变化,就是引入了长连接,即TCP连接默认不关闭,可以被多个请求复用。一个TCP连接可以允许多个HTTP请求。使用长连接的HTTP协议,会在响应头加入Connection: keep-alive
。
在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。若客户端和服务器发现对方一段时间没有活动,就可以主动关闭连接。不过,规范的做法是,客户端在最后一个请求时,发送Connection: close
,明确要求服务器关闭TCP连接。
- 实现长连接需要客户端和服务端都支持长连接。
- HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
- 目前,对于同一个域名,大多数浏览器允许同时建立6个持久连接。
管道机制
1.1版本还引入了管道机制,即在同一个TCP连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。
举例来说,客户端需要请求两个资源。以前的做法是,在同一个TCP连接里面,先发送A请求,然后等待服务器做出回应,收到后再发出B请求。管道机制则是允许浏览器同时发出A请求和B请求,但是服务器还是按照顺序,先回应A请求,完成后再回应B请求。
服务端是按队列顺序处理请求的,服务器只有处理完一个回应,才会进行下一个回应。假如前面的请求处理时间很长,后面就会有许多请求排队等着,这样就造成了“队头阻塞”的问题。
分块传输
对于一些很耗时的动态操作来说,这意味着,服务器要等到所有操作完成,才能发送数据,显然这样的效率不高。更好的处理方法是,产生一块数据,就发送一块,采用"流模式"(stream)取代"缓存模式"(buffer)。
HTTP2.0
因为http协议的庞大冗余,因此2.0不是新增特性,而是重新定义http协议。
在2.0版本中:
1.使用二进制数据传输。
2.支持主动推送资源。允许服务器未经请求,主动向客户端发送资源。
3.服务器进行长连接响应,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了"队头堵塞"。
举例来说,在一个TCP连接里面,服务器同时收到了A请求和B请求,于是先回应A请求,结果发现处理过程非常耗时,于是就发送A请求已经处理好的部分, 接着回应B请求,完成后,再发送A请求剩下的部分。
响应行
响应行:协议版本空格
响应状态码空格
状态码描述\r\n
响应状态码:直观的向客户反馈处理结果
HTTP状态码分类:
HTTP状态码列表:
头部
头部:关于请求或响应,或者正文的一些描述字段。
组成:key: value\r\n
典型头部字段:
Connection:
长短连接控制。keep-alive/close
Referer:
记录本次请求的来源链接Content-Type:
用于表示正文的数据格式Content-Length:
用于表示正文的长度,http解决粘包问题的关键字段Location:
用于指定重定向的新链接地址,与3xx搭配使用
Cookie与Session
http协议是一种无状态的协议,浏览器对服务器的每一次请求都是独立的。为了使得页面能够产生一些动态信息,就需要保存”状态”,而cookie和session机制就是为了解决http协议无状态而产生。cookie是一种在客户端保存状态的方案,session是一种在服务器端保存状态的方案。
Cookie
- 一个客户端登录浏览器之后,服务端验证登录,成功之后,从服务器端发送的响应报文内头部字段
Set-Cookie
设置cookie信息(用户信息,状态等)返回给客户端。 - 客户端收到响应后,将Set-Cookie字段的cookie信息保存起来,下次请求服务器的时候从cookie文件中读取出cookie信息,通过请求报文内头部字段
Cookie
发送给服务器。
由于cookie中包含了一些敏感信息,虽然信息经过加密,但是如果被别人截获,那么只要把cookie向服务器提交,那么就可以冒充其他人访问服务器,存在安全隐患。所以就提出session解决此问题。
Session
session是服务端针对每个客户端所建立的会话,当客户端登录成功后,在服务端创建会话,在会话中记录客户端用户信息以及状态等,而只在客户端记录一个session id用于区分是哪个用户的session。
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含一个session id。如果有则表明已经为此客户端创建过session,服务器就按照这个session id查找出服务器端保存的session(查找失败的话,会创建一个新的session)。如果请求中不包含session id,则就回创建一个新的session,通过Set-Cookie字段将session id返回给客户端,客户端进行保存。
session需要在客户端存储一个session id。可以将这个值存储在Cookie,每次发送请求时通过Cookie请求头将其发送到服务器;也可以不使用Cookie,而将session id做为一个额外的请求参数,通过URL或请求体发送到服务器。
Cookie与Session的区别
Cookie是维护http通信状态的技术,将关键信息保存在客户端,每次请求服务器时,读取出来发送给服务端(存在安全隐患)。
Session是解决cookie安全隐患的技术,将关键信息保存在服务器,将session id发送给客户端,作为cookie保存起来,往后请求传输session id即可,解决了cookie泄密的风险。
总体来说Cookie与Session的区别:
(1)cookie数据存放在客户的浏览器上,session数据放在服务器上
(2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,如果主要考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用cookie
(4)单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的cookie不能3K。
(5)所以:将登陆信息等重要信息存放为session;其他信息如果需要保留,可以放在cookie中
空行
空行:\r\n
。是与头部最后一个字段的结尾\r\n组成连续的\r\n\r\n
作为http头部结尾的标志。
正文
http是一个应用层协议,只是应用程序如何沟通的一种数据格式约定,在传输层是基于tcp协议实现的。
http客户端实际就是一个tcp客户端,http服务器实际上就是一个tcp服务器,只不过http客户端与服务端的通信使用的是http协议来约定数据格式而已。
简单的http服务器的搭建
服务器搭建流程:
1.搭建tcp服务端
2.获取新建连接
3.使用新建连接,等待接收数据(http协议的请求数据)
4.接收过程:先接收http头部,解析头部Content-Length确定正文长度
5.接收指定长度的正文
6.根据请求方法以及资源路径确定客户端的请求目的
7.进行具体对应的业务处理
8.组织http协议格式的响应数据,对客户端进行恢复
9.如果是短连接,则直接关闭套接字;如果是长连接,则继续等待接收数据
简单的http服务器代码:
tcp.hpp
是Linux网络编程 | Socket编程:TCP服务器单执行流、多线程、多进程的实现中TCPSocket的封装
#include"tcp.hpp" #include<sstream> int main() { TcpSocket lst_socket; //创建套接字 CHECK(lst_socket.Socket()); //绑定地址信息 CHECK(lst_socket.Bind("192.168.134.141", 9000)); //开始监听 CHECK(lst_socket.Listen()); while(1) { //获取新建连接 TcpSocket newSocket; string ip; uint16_t port; bool ret = lst_socket.Accept(newSocket, &ip, &port); if(ret == false) continue; //接收数据 string buf; ret = newSocket.Recv(buf); if(ret == false) { newSocket.Close(); continue; } cout << "request:[" << buf << "]\n"<< endl; buf.clear(); //发送数据 //组织数据格式 stringstream ss; string body = "<html><body><h1>Hello World</h1></body></html>"; ss << "HTTP/1.1 200 OK\r\n"; ss << "Content-Length: " << body.size() << "\r\n"; ss << "Content-Type: text/html;charset=UTF-8\r\n"; ss << "Connection: close\r\n"; ss << "Location: https://www.baidu.com\r\n"; ss << "\r\n"; ss << body; buf = ss.str(); cout << "response:[" << buf << "]\n" << endl; ret = newSocket.Send(buf); if(ret == false) { newSocket.Close(); } } //关闭套接字 lst_socket.Close(); return 0; }
注意:
http服务器编写完毕之后:
- 云服务器:记得设置安全组策略,开启对应端口
- 虚拟机:记得关闭防火墙
sudo systemctl stop firewalld
示例:
输入URL后发生了什么
- 浏览器向DNS服务器请求解析该URL中的域名对应的IP地址
- 解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接
- 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器
- 服务器对浏览器请求作出相应,并把对应的html文本发送给浏览器 释放TCP连接
- 浏览器解析HTML文本并局部渲染
这篇关于超详细的HTTP协议的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14后台交互资料入门指南
- 2024-11-14如何轻松创建项目环境:新手入门教程
- 2024-11-14如何抽离公共代码:初级开发者指南
- 2024-11-14Python编程入门指南
- 2024-11-14Python编程入门:如何获取参数
- 2024-11-14JWT 用户校验:简单教程与实践
- 2024-11-14Pre-commit 自动化测试入门指南
- 2024-11-14Python编程基础
- 2024-11-14Server Action入门教程:轻松掌握服务器操作
- 2024-11-14Server Component入门教程:轻松搭建服务器组件