HTTP是什么?
HTTP协议也叫Hyper Text Transfer Protocol(超文本传输协议),工作在OSI参考模型的应用层,是一个基于请求与响应模式的无状态的协议,同时也是基于TCP/IP协议来传输数据。
HTTP主要特点
1、主要支持B/S模式:平常我们使用的浏览器可根据url向服务器发送请求,服务器拿到HTTP报文之后解析并作出响应,将数据传输回浏览器,TCP三次握手建立连接之后传输数据就是HTTP报文与其他的服务器资源
2、简单快速:客户端向服务器请求服务时,只需要传输请求方法(比如:GET,POST,PUT等等)和路径(即URL资源定位符)服务器收到就会将对应的资源和响应返回给客户端
3、灵活:HTTP允许传输任意数据对象,正在传输的类型由Content-Type加以标记。
4、无连接:每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。但是在HTTP1.1版本之后,在HTTP1.1中已经默认使用Connection: keep-alive,避免了连接建立和释放的开销,但服务器必须按照客户端请求的先后顺序依次回送相应的结果,以保证客户端能够区分出每次请求的响应内容。通过Content-Length字段来判断当前请求的数据是否已经全部接收。不允许同时存在两个并行的响应。但是无连接永远是HTTP的特性,至于下层的TCP连接是否关闭已经不在HTTP管辖范围之内,所以HTTP协议还是无连接的
5、无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
HTTP请求结构
下面是我访问https://www.baidu.com的HTTP请求报文
GET https://www.baidu.com/ HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: keep-alive
Cookie: ***
Host: www.baidu.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36
下面是响应报文头部字段名的含义
Accept:浏览器可接受的文件类型。
Accept-Charset:浏览器可接受的字符集。
Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
Connection:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。
Content-Length:表示请求消息正文的长度。
Cookie:这是最重要的请求头信息之一,某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)就是cookie。所以比较重要,不能随意让其他人获取到自己在网页上的Cookie
From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
Host:初始URL中的主机和端口。
If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。
Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。
Referer:包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。
UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型。
但是浏览器不一定发所有的请求头字段,而是选取需要的发送,每个网页发送的请求头字段都不一样
HTTP响应报文结构
下面是百度传回来的响应报文
HTTP/1.1 200 OK
Bdpagetype: 2
Bdqid: 0xd24a0cab000b1e6e
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Wed, 08 May 2019 03:23:24 GMT
Expires: Wed, 08 May 2019 03:23:24 GMT
Server: BWS/1.1
Set-Cookie: ***
Set-Cookie: ***
Set-Cookie: ***
响应正文就是百度的前端界面代码,最终浏览器会将这个前端展示给我们
下面是响应报文头部字段名的含义:
Allow 服务器支持哪些请求方法(如GET、POST等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。Java的GZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即 request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入ByteArrayOutputStram,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它
Last-Modified 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302。
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。注意这种功能通常是通过设置HTML页面HEAD区的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用CGI或Servlet的HTML编写者十分重要。但是,对于Servlet来说,直接设置Refresh头更加方便。注意Refresh的意义是“N秒之后刷新本页面或访问指定页面”,而不是“每隔N秒刷新本页面或访问指定页面”。因此,连续刷新要求每次都发送一个Refresh头,而发送204状态代码则可以阻止浏览器继续刷新,不管是使用Refresh头还是<META HTTP-EQUIV="Refresh" ...>。注意Refresh头不属于HTTP 1.1正式规范的一部分,而是一个扩展,但Netscape和IE都支持它。
Server 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie 设置和页面关联的Cookie。Servlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie。参见下文有关Cookie设置的讨论。
WWW-Authenticate 客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm="executives"")。注意Servlet一般不进行这方面的处理,而是让Web服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。
下面是常见状态码的含义:
1XX:接受的请求正在处理
2XX:请求正常处理完毕
200 OK:请求已经正常处理
204 No Content:请求处理成功但没有资源返回
206 Partial Content:是对资源的一部分请求,即响应报文中包含Content-Range指定的范围实体
3XX:需要进行附加操作以完成请求
301 Moved Permanently:也就是URI在服务器端更新,客户端也要进行书签引用的变更
302 Found:只是临时重定向和301状态码有些相似,但是301是永久性的
303 See Other:303和302有着相同的功能,但303状态码表示客户端需要用到GET的方式进行请求
304 Not Modified:表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但是请求未能满足服务器所设置的条件
307 Temporary Redirect:临时重定向。302有相同的含义。307会遵照浏览器的标准。
4XX:服务器无法处理请求,可以理解为客户端发送的请求信息有误
400 Bad Request:表示请求报文中存在语法错误
401 Unauthorized:表示发送的请求需要有通过HTTP的认证信息,若之前有过请求,这表示请求失败
403 Forbidden:表明对请求资源的访问被服务器拒绝了,但如果想做说明的话,需要在实体的主体部分对原因进行描述
404 Not Found:服务器中没有找到资源,或者拒绝访问又不想说明理由的时候
5XX:服务器处理请求出错。错在服务器这边
500 Internal Server Error:表明服务器端在执行请求的时候出现了错误
503 Service Unavailable:表示服务器正处在超负载或正在进行停机维护
HTTP请求响应步骤
1、客户端(通常是浏览器)连接到Web服务器(一般默认端口号是80),这时候会建立一个套接字连接
2、发送HTTP请求,通过套接字,客户端就可以向Web服务器发送一个请求报文
3、服务器接收请求并返回HTTP响应,也就是Web服务器解析请求定位请求资源,而后服务器再将资源副本写到TCP套接字由客户端读取
4、如果连接模式为close,那么服务器会主动关闭连接,而客户端是被动关闭连接,若连接模式为keep-alive那么连接就会保持一段时间
5、最后这一步就是浏览器解析HTML内容,首先会检查状态行看是否成功,然后解析每一个响应头,最后就是解析前端HTML代码。浏览器会根据状态码来查看是否要接着解析,比如出现404状态码,浏览器就会展示异常给我们,同样这时它是拿不到响应正文的。
三道面试常考题
1、在浏览器键入URL,按下回车之后的流程是什么?
(1)、DNS解析:浏览器会根据URL逐层查询DNS服务器缓存,解析出URL中的域名所对应的IP地址。DNS缓存分别有浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存。从上面的哪一级缓存查询到后直接返回IP地址,不再查询。
(3)、发送HTTP请求:在浏览器和服务器之间建立好连接之后,浏览器就会发送HTTP请求报文
(4)、服务器处理请求并返回HTTP报文:服务器返回给浏览器带有HTML的响应报文
(5)、浏览器解析渲染页面
(6)、浏览器释放连接,即TCP四次挥手。
2、GET和POST区别
先来看看请求方法有哪些:
OPTIONS:返回服务器所支持的请求方法
GET:向服务器获取指定资源
HEAD:与GET一致,但是只返回响应头,不返回响应正文
POST:向服务器提交数据,数据放在请求体里
PUT:与POST相似,只是具有幂等特性,一般用于更新
DELETE:删除服务器指定资源
TRACE:回显服务器端收到的请求,测试的时候会用到这个
CONNECT:预留,暂无使用
而GET和POST作为最常用的两个请求方法,究竟区别在哪?
1、最直观的就是GET会将请求的参数放在URL中,由于URL有长度限制,所以参数不能太多,而POST的参数是放在请求报文的正文中,长度没有限制。
2、GET方式主要是对数据库进行查询,所以GET是符合幂等性(对数据库无论操作多少次返回的结果是一样的)和安全性(不修改数据库),而POST主要用于让数据库增加数据或者删除,修改数据,所以会有一定的安全性问题,需要对POST提交的参数做一些安全性检验。
3、GET方式还能被缓存被存储,GET请求的URL会保存在浏览器的历史记录中,而缓存也是GET请求被广泛应用的根本,而POST方式除非手动设置,不然不会被缓存。
4、GET方式下产生一个TCP数据包,POST产生两个数据包。对于GET方式,浏览器会把HTTP请求报文发出去,服务器响应200之后返回响应报文,而POST则是浏览器先发HTTP请求头,服务器响应100 continue之后浏览器再发从请求正文过去,服务器响应200并返回数据(但是在Firefox浏览器POST就只发一次数据包)
3、Cookie和Session的区别
前面我们说过HTTP是无状态的,也就是没有记忆功能,那我们的自动登录都是怎么样实现的呢?主要是两种
第一种方法(浏览器):使用Cookie。Cookie是服务器发给浏览器的特殊信息,并会以文本形式存在浏览器中,所以我们点击浏览器的清除记录,往往会问我们是否清理Cookie,当清理之后下次再访问网页就会需要我们重新登录。如果浏览器中存在Cookie,那么提交请求就会一起提交过去服务器在接收到后就会解析Cookie生成与客户端相对应的内容,实现自动登录,Cookie带有我们的比较重要信息,所以一般不要给被人获取
第二种方法(服务器):使用Session。Session是在服务器上保存的信息,当服务器需要为客户创建Session的时候,就会解析客户端请求查看请求是否包含session id,如果包含那么就表明此前已经为客户端创建过session,不包含则创建一个对应的session id,而后回发给客户端,使得客户端下次能带有session id。然后按需保存状态
所以最终的区别总结起来就是:Cookie数据存放在客户浏览器上,Session数据存放在服务器上,Session相对应Cookie安全,而使用Cookie会给服务器减负
彩蛋:
在访问百度首页,使用浏览器的开发者工具查看console的时候会发现
这也算我写这篇博客的一个收获吧