超详细的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

  1. 一个客户端登录浏览器之后,服务端验证登录,成功之后,从服务器端发送的响应报文内头部字段Set-Cookie设置cookie信息(用户信息,状态等)返回给客户端。
  2. 客户端收到响应后,将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后发生了什么

  1. 浏览器向DNS服务器请求解析该URL中的域名对应的IP地址
  2. 解析出IP地址后,根据该IP地址和默认端口80,和服务器建立TCP连接
  3. 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP三次握手的第三个报文的数据发送给服务器
  4. 服务器对浏览器请求作出相应,并把对应的html文本发送给浏览器 释放TCP连接
  5. 浏览器解析HTML文本并局部渲染

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…