http协议详解

前言

对于http协议,每个人都或多或少地会用到它,因为浏览器的地址栏就有,比如 http://www.baidu.com

HTTP协议

1.http协议简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

  • 应用层协议
  • 基于TCP/IP
  • 默认端口号:80
  • 可用来传递数据(HTML文件, 图片文件, 查询结果等)
2.网站访问过程
UTOOLS1576638811838.png

首先由Client向Server发起请求,发送HTTP request。
Server收到请求后,进行响应,发送HTTP response。

整个过程可以归纳如下:

  1. Client向Server发送HTTP request
  2. 服务器发送状态码,比如"HTTP/1.1 200 OK\r\n\r\n"
  3. 服务器发送网页文件(HTTP response)
3.http请求消息

消息包括以下格式:请求行+请求头部+空行+请求数据,总共四个部分

UTOOLS1576649985547.png

举例:

请求行:

POST /examples HTTP/1.1\r\n		//请求方式,请求路径和协议版本

请求头:

Accept: application/x-ms-application, image/jpeg, application/xaml+xml, image/gif, image/pjpeg, application/x-ms-xbap, */*		//客户端向服务器端表示,我能支持什么类型的数据
Referer: http://localhost:8080/examples/servlets/servlet/RequestParamExample		//告诉服务器我是从哪一个页面链接过来的
Accept-Language: zh-CN			//支持语言格式
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)	//客户端信息
Content-Type: application/x-www-form-urlencoded		//提交的数据类型。经过urlencoding编码的form表单的数据
Accept-Encoding: gzip, deflate	//gzip, deflate为压缩算法 
Host: localhost:8080			//服务器地址
Content-Length: 31				//数据长度
Connection: Keep-Alive			//Keep-Alive保持连接
Cache-Control: no-cache			//对缓存的操作

请求体:

firstname=zhang&lastname=sansan	//发送给服务器的数据
4.请求方式

请求方式在请求头中的第一个字段

序号方法描述
1 GET(常用) 请求指定的页面信息,并返回实体主体。 请求信息包含在URL中
2 POST(常用) 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。请求数据被包含在请求体中。
3 HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
4 PUT 从客户端向服务器传送的数据取代指定的文档的内容。
5 DELETE 请求服务器删除指定的页面。
6 CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
7 OPTIONS 允许客户端查看服务器的性能。
8 TRACE 回显服务器收到的请求,主要用于测试或诊断。
9 PATCH 是对 PUT 方法的补充,用来对已知资源进行局部更新 。

比如:

https://www.baidu.com/s?ie=UTF-8&wd=滴滴    //GET方式,数据包含在URL中

从上面的URL可以得到信息:

  • ie的值为"UTF-8"
  • wd的值为"滴滴"

Server根据这些请求的数据,经过一定的程序逻辑,返回响应页面。

5.状态码

再次回顾网页访问的过程:

  1. Client向Server发送HTTP request
  2. 服务器发送状态码,比如"HTTP/1.1 200 OK\r\n\r\n"
  3. 服务器发送网页文件(HTTP response)

状态码用于告知Client当前的Server状态。

状态码分类与常见状态码:

1xx //信息提示
	100 continue	继续发送
2**	//成功状态码
    200	OK(请求成功)
3**	//重定向
    301 永久重定向(搜索引擎会将排名等信息转移到新域名)
    302 临时重定向(搜索引擎不会将排名等信息转移到新域名)
4**	//客户端错误
    403	Forbidden(客户端没有权限访问此资源)
    404	NotFound(资源不存在)
  499 (请求未完成,但客户端主动断开了连接,这是nginx引入的非标状态码) 5** //服务器错误 500 服务器内部出错(如Bug) 502 错误网关(网关向后端请求错误) 503 服务不可用(服务器无法处理请求,比如过载) 504 网关超时(网关向后端请求超时)

滴滴官网的404界面:

UTOOLS1576652236170.png
6.http响应

http响应头部和请求的头部类似:响应行+响应头+响应体
响应体为网页文件等资源

响应行:

HTTP/1.1 200 OK		//协议版本,状态码,OK对应状态码

响应头:

Server: Apache-Coyote/1.1		//服务器类型,这里是Tomcat
Content-Type: text/html;charset=ISO-8859-1	//返回数据类型
Content-Length: 673				//返回数据长度
Date: Fri, 17 Feb 2017 02:53:02 GMT			//响应时间
响应头说明
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,Servlet应该通过查看Accept-Encoding头(即request.getHeader(“Accept-Encoding”))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。
Content-Type 表示后面的文档属于什么类型。比如text/html。
Date 当前的时间。
Expires 文档过期时间,过期后浏览器可不再缓存
Last-Modified 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。
Location 重定向后的位置。比如301永久重定向和302临时重定向
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。
Server 服务器名字。
Set-Cookie 设置和页面关联的Cookie。
7.http协议特点

(1) 媒体独立

所有类型的数据都可以通过http协议传输。传输的类型由Content-Type标明。

(2) http协议是无状态的

无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。
cookie和session技术让服务器有了记忆。

UTOOLS1576655220620.png UTOOLS1576655265287.png UTOOLS1576655313756.png UTOOLS1576655333877.png

(3) http是无连接的

无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。

早期的服务器资源有限,采用无连接的方式以便腾出资源处理其他请求。

无连接产生的问题:

随着时间的推移,网页中嵌入了图片和其他元素,并且是以链接的方式嵌入。这就说明,客户端在请求完网页文件后,紧接着又会向服务器请求图片等静态资源。这样的话,无连接+多次请求就极大的浪费了带宽等资源(都浪费在TCP上了)。

如何解决?

  • 使用Keepalive长连接。
8.http长连接

在HTTP/1.0中,默认使用的是短连接。
从HTTP/1.1起,默认使用长连接。
使用长连接的HTTP协议,会在响应头有加入这行代码:Connection:keep-alive

在使用长连接的情况下,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的 TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。Keep-Alive不会永久保持连接,一段时间后会断开。
比如:客户端和服务器之间会继续使用这个通道传输图片等资源。

服务器会和客户端保持一段空闲连接,在此期间他们可以无需连接即可传输数据。空闲时间到期后(默认2h),服务器会发送探测多个报文给客户端,如果都没有回应或回应断开连接的报文,则断开连接。

UTOOLS1576656783233.png

HTTP协议的长连接和短连接,实质上是TCP协议的长连接和短连接。
可以看到,长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间。对于频繁请求资源的客户来说,较适用长连接。

9.HTTP2.0

新的二进制格式(Binary Format)

HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。

多路复用(MultiPlexing)

即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。

header压缩

如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。

服务端推送(server push)

同SPDY一样,HTTP2.0也具有server push功能。

详细解释可以看这里:https://www.cnblogs.com/heluan/p/8620312.html

10.Web Socket

这是HTML5的协议
传统http只能由客户端请求,服务端回应。如果客户端定时请求,则会造成很大资源浪费。
Web Socket可以握手,实现真正的双向传输。这样有数据更新的时候服务端可以及时发送数据,也不会造成资源浪费。
详细介绍可是看这里:https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096

Web Socket握手过程:

首先,WebSocket连接必须由浏览器发起,因为请求协议是一个标准的HTTP请求,格式如下:

GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string
Sec-WebSocket-Version: 13

解释:

GET请求的地址不是类似/path/,而是以ws://开头的地址;
请求头Upgrade: websocketConnection: Upgrade表示这个连接将要被转换为WebSocket连接;
Sec-WebSocket-Key是用于标识这个连接,并非用于加密数据;
Sec-WebSocket-Version指定了WebSocket的协议版本。

服务端回应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: server-random-string
11.Linux网络优化

由于长连接会占用大量资源,典型的就是出现大量的TIME_WAIT。

可以通过下面的命令查看TIME_WAIT等状态的数量:

netstat -ant|awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}'

推荐配置:

vim /etc/sysctl.conf
    #TCP的配置
    net.ipv4.tcp_syn_retries=2		#最多发起2次SYN请求(默认为5)
    net.ipv4.tcp_fin_timeout=30		#FIN_WAIT_2时间
    net.ipv4.tcp_max_syn_backlog = 4096	#SYN队列长度(默认为1024),增加以容纳更多等待连接数
    net.ipv4.tcp_tw_reuse = 1		#开启TIME-WAIT sockets重用机制(默认为0,即关闭),可重新用于新的TCP连接
    net.ipv4.tcp_tw_recycle = 1		#开启TIME-WAIT sockets快速回收(默认为0,即关闭)
    net.ipv4.tcp_syncookies = 1		#当SYN等待队列溢出时,启用cookies来处理(默认为0,即关闭),可以防范少量SYN攻击
    #http的keepalive长连接的配置
    net.ipv4.tcp_keepalive_time=1200	#空连接可以保持1200s
    net.ipv4.tcp_keepalive_probes=5	#空连接结束后发送探测报文的个数(都未回应则断开连接)
    net.ipv4.tcp_keepalive_intvl=20	#每个探测包的间隔时间
    #其他配置
    net.core.netdev_max_backlog=3000	#每个网络接口接收数据包的速率比内核处理这些包的速率快时,允许送到队列的数据包的最大数目
sysctl -p	#加载内核文件

HTTPS协议

  • 超文本传输安全协议,Hypertext Transfer Protocol Secure
  • HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。

背景:

  • http协议是不安全的,所有的数据都是明文传输的。
  • http的明文传输使得密码等信息可以通过抓包轻松得到。
1. SSL/TLS协议

HTTPS就是在应用层和传输层中间加了一道验证的门槛以保证数据安全:

UTOOLS1576663283549.png

什么是SSL/TLS?

  • SSL(Secure Socket Layer) 安全套接层
  • TLS(Transport Layer Security) 传输层安全
  • TLS与SSL在传输层对网络连接进行加密。

1996年 NetScape 公司发布 SSL v3.0;
1999年互联网标准化组织ISOC接替NetScape公司,发布了SSL的升级版TLS 1.0版。
2006年和2008年,TLS进行了两次升级,分别为TLS 1.1版和TLS 1.2版。
SSL 及其继任者 TLS 是为网络通信提供安全及数据完整性的一种安全协议。

2. SSL/TLS协议基本过程

(1) 客户端向服务器端索要并验证公钥。
(2) 双方协商生成"对话密钥"。
(3) 双方采用"对话密钥"进行加密通信。
前两步,又称为"握手阶段"。

UTOOLS1576663691154.png

注意点:

  • 握手阶段使用非对称加密。
  • 数据传输阶段使用对称加密。

背景知识:

  • 非对称加密中:公钥加密,私钥解密。(私钥只有Server有,公钥在证书中)
  • 对称加密中: 双方秘钥相同,既可加密,也可解密。 对称加密非常快,而非对称加密非常慢。

问题1:为什么要使用对称加密?

  • 对称加密非常快,而非对称加密非常慢。

问题2:为什么不直接使用对称秘钥?

  • 不能直接发送对称秘钥,这样就会被第三方获取。
  • 因为随机数a和b都是明文,所以随机数c不能被第三方得到。
  • 为了能让Server得到c,使用公钥加密该随机数,这样只有Server可以解析。

问题3:公钥从哪里来,可否伪造?

  • 私钥签名,公钥验签,所以不可伪造。
  • 公钥在证书中。
  • 客户端会查看Server的证书,若可信则继续协议过程,若不可信则拦截。计算机中保存了一些可信的CA机构,若此证书是可信的CA机构颁发的,则信任,否则不信任(会提示用户,依然可以访问)。
  • 可以通过手动导入证书的方式信任此证书。

问题4:HTTP不安全为什么还要用呢?

  • 可以在前端实现加密。
  • 使用https需要额外的运维、计算和证书购买成本。
  • HTTPS连接服务器端资源占用高
  • HTTPS协议握手费时
  • SSL证书费用成本
  • http访问速度快
posted @ 2019-12-19 19:29  NetRookieX  阅读(6)  评论(0编辑  收藏  举报