Java教程

仔细想想还是再看看HTTP比较好

本文主要是介绍仔细想想还是再看看HTTP比较好,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

HTTP

引言

HTTP协议全称为HyperText Transfer Protocol(超文本传输协议),它是WWWIETF发布的一系列RFC的规范。比如我们现在常用的HTTP/1.1RFC 2616定义的。

1594616132980

RFC是一种当某机构或某人对开发出的一套标准或设想,要征询外界意见时,发布在Internet上的文件,该文件相当于一个说明文件,用于其他人阅读并提出意见。

HTTP协议是在TCP协议之上的,当然也可以构建于TLS/SSL之上,此时它就成为了更具安全性的HTTPS

HTTP可以基于UDP方式传输吗?

我们知道UDP是不可靠传输,只负责发出数据包,并不管目标主机是否接收到。而HTTP又是无状态的协议(关于无状态协议的概念可以看这篇知乎的问答:HTTP是一个无状态的协议。这句话里的无状态是什么意思?),没头脑配上鱼的记忆,这就是一场灾难......。HTTP在任何传输层协议都可以,所以按理来讲也可以用UDP,但是可能要做好删库跑路的准备。

HTTP 结构

HTTP1和HTTP2的消息结构对于用户来说是透明的,不需要对旧的配置文件进行改动就可以过渡到HTTP2。两者之间的区别如下:

1594644695281

对于HTTP2,较大的区别在于它将 HTTP/1.x 消息分成帧并嵌入到流 (stream) 中。数据帧和报头帧分离,这将允许报头压缩。将多个流组合,这是一个被称为 **多路复用 (multiplexing)***的过程,它允许更有效的底层 TCP 连接。

1594644781069

抓一下HTTP的包,来分析一下 HTTP的消息结构:

1594620974199

HTTP的消息结构包括请求消息结构和响应消息结构,下面对此分别进行解析。

请求消息

HTTP请求消息包括请求行、请求头部、请求数据以及填充符\r\n。下面是请求报文的一般格式:

1594621174955

对照此结构,我们可以知道在上图中的报文里的请求方式为GET,以及它的请求路径,还有它请求头部的数据。

各后端开发语言的Web开发框架都会提供对请求报文的解析支持,可以通过类似request.getHead方法来获取请求的头部,并对其进行相关操作。

请求头能给我们提供很多信息,这里推荐这篇博客,写的挺全的:HTTP请求头--那些你需要记住的基础知识

From Data和Request Payload

对于GET方法的请求参数,就是直接拼接在请求URL后面,但对于POST的请求数据,游览器有两种处理方法:Form DataRequest Payload

比如当我们使用HTML表单的方式直接提交数据,那么POST数据是这样的:

1594622418106

如果使用ajax来提交,那么格式会发生变化:

1594623255798

我们可以看到ajax默认的提交的coontent-typetext/plain;charset=UTF-8,而此时表单的数据跟GET参数一样被拼接在一起。

而当我们指定Content-typeapplication/x-www-form-urlencoded时,数据格式又发生了变化,传到后端时就变成了json数据:

1594623358307

根据上面的示例,我们可以看出POST提交对于游览器有两种解析方法,一种是FormData,一种是Request Payload,而它们都是属于请求体的内容,表现形式取决于content-type的指定。

这也是为什么有的时候对于POST请求,后端获取不到值的原因:由于content-type的指定导致数据传输形式的不同。

在以前的HTTP中,一般都是使用GETPOST请求资源,但是在更新后的HTTP1.1中新增了五种请求方法:OPTIONSPUTPATCHDELETETRACECONNECT,这些请求方法的增加是RESTFUL风格接口实现的基础。具体的常用方法说明如下:

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

响应消息

响应消息的结构和请求消息差不多,主要关注的部分是响应头和响应数据,响应数据就是后端返回给前端的数据,下面我们来看看响应头包含的信息和作用。

响应头会告诉游览器服务端的相关信息和数据信息等,比如下面所示:

1594626384526

对于CORS,它是一种跨资源共享机制,当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求,游览器本身默认是不支持跨域请求的,所以我们需要在响应头进行配置,告诉游览器请求方是可以获取该资源的,你就不要拦截了。

对于Transfer-Encoding要和Content-Encoding进行比较,Conotent-Encoding是内容编码的策略,比如是否进行压缩,目的是为了优化传输。而Transfer-Encoding是为了指定报文的格式,比如为了减少每次TCP三次握手的时间,我们采用持久连接获取数据,即打开一个连接传输数据后并不关闭连接,而是可以进行复用。如果我们不指定数据的长度的话,那么游览器会因为连接没有中断而认为数据没有传输完,那么请求就会一直处于padding状态,此时我们可以通过设置Content-Length来告诉游览器这个数据的长度是多少。虽然这种方法可以解决问题,可以如果频繁地读取大量数据,那么不断获取数据长度就会影响服务器的性能,而改进的方法就是指定Transfer-Encoding

在头部加入 Transfer-Encoding: chunked 之后。就表示进行分块编码,每个分块包含十六进制的长度值和数据,长度值独占一行,长度不包括它结尾的 CRLF,和分块数据结尾的 CRLF。最后一个分块长度值为0,对应的分块数据没有内容,表示数据传输结束。

对比Content-EncodingTransfer-Encoding,我们可以看出Transfer-Encoding是作用于传输的格式,而Content-Encoding则是指定游览器获取数据后对数据进行的解析格式。

Vary则是作用于代理服务器/缓存/CDN,指定对于请求的判断表哦准,比如Vary中有User-Agent,即对于相同的请求,如果用户使用不同的网页打开,那么代理服务器/缓存/CDN会认为是不同的请求,而如果Vary中没有User-Agent,那么它们会认为是相同的页面,直接给用户返回缓存的页面。

服务端和游览器的Cookie

在以前,因为HTTP的无状态性,我们经常使用Cookie来存储用户凭证,一般来说就是服务端将相关信息存入一个new Cookie()中,然后用response.setCookie(cookie)就可以了,而客户端则可以收到这个Cookie。这样就让人很迷,我客户端啥都没干,怎么就获取到了Cookie?

实际上,当服务单设置了Cookie后,将会给返回游览器的响应消息的消息头加上set-cookie信息,游览器会根据响应消息头来自动设置Cookie,不需要前端显式进行操作,而对于后面的请求,每次也会自动带上Cookie。

Cookie的工作机制是由RFC 6265规定的,对于Cookie还可以指定过期时间、特定域名(用于防止跨域)、路径。

服务端和游览器的Session

处理Cookie外,Web应用还可以使用Session来记录客户端的状态,它是服务端记录客户端状态的机制。服务端会给客户端分发一个SessionID作为唯一标识,对于SessionID可以存储在Cookie中,也可以作为请求URL中的参数,服务端每次处理请求前都会看下这个SessionID是否存在于自己存储的数据中。

Session和Cookie的区别可以用这么个情况来表示:

老王开了一家理发店,因为老王的记性很差,所以为了给老客户优惠,都会给他们一张卡片 ,卡片上面有该客户的个人信息,客户来理发时老王只要看下卡片就知道怎么办了。卡片记录这客户的信息,而卡片在客户手上。这就是Cookie。

后来老王的客户越来越多 ,为了更好地提高服务 ,老王就在卡片上面加了很多内容,比如客户的消费次数、一般什么时候来、喜欢什么发型、脾气怎么样等等,这样卡片就越来越大,让客户每次带着都不方便。所以老王就把信息做成一本书,放在自己这里,每一项信息都有一个对应的唯一id,老王只要把id写在卡片上给对应的用户,下次用户只要带一张小小的卡片过来,给老王一看卡片上的id,老王就可以查出该用户的信息了。卡片只是记录了用户id,而详细的数据是在老王这里。这就是Session。

总结

对于HTTP协议的规则,可以查看MDN HTTP协议。

这篇关于仔细想想还是再看看HTTP比较好的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!