熟悉HTTP对于我们的工作有非常大的帮助,原因如下:
- HTTP 是前后端合作的重要方式;
- HTTP帮助我们从本质上理解HTML JS CSS JSON JSONP图片等不同形式的资源;
- Web性能优化基本等价于对HTTP传输效率的优化;
- 前端工程化需要对HTTP缓存有深入了解。
下面就让我们通过与HTTP有关的面试题来巩固HTTP知识吧。
1.简单说说什么是HTTP?
HTTP是一个超文本传输协议,是基于TCP协议的,TCP是一个双向的通信通道,HTTP在TCP的基础上规定了request-response模式。这个模式就确定下来通信必须是由客户端向服务端发起的。
HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范。
2.谈一谈HTTP的特点和缺点
特点:
- 灵活可扩展:一个是语法上只规定了基本格式,空格分隔单词,换行分隔字段等。另外一个就是传输形式上不仅可以传输文本,还可以传输图片,视频等任意数据
- 请求-应答模式:通常而言,就是一方发送消息,另外一方要接受消息,或者是做出相应等
- 可靠传输:HTTP是基于TCP/IP,因此把这一特性继承了下来
- 无状态:这里的状态是指通信过程的上下文信息,而每次 http 请求都是独立、无关的,默认不需要保留状态信息
缺点:
- 无状态:有时候,需要保存信息,比如像购物系统,需要保留下顾客信息等等,另外一方面,有时候,无状态也会减少网络开销,比如类似直播行业这样子等,这个还是分场景来说
- 明文传输:即协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。这让HTTP的报文信息暴露给了外界,给攻击者带来了便利
- 队头阻塞:当http开启长连接时,共用一个TCP连接,当某个请求时间过长时,其他的请求只能处于阻塞状态,这就是队头阻塞问题
3.谈一谈HTTP1.0、HTTP1.1和HTTP2.0版本之间的差异
HTTP1.0:
- 任何格式的内容都可以发送,这使得互联网不仅可以传输文字,还能传输图像、视频、二进制等文件。
- 除了GET命令,还引入了POST命令和HEAD命令。
- http请求和回应的格式改变,除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据。
- 只使用 header 中的 If-Modified-Since 和 Expires 作为缓存失效的标准。
- 不支持断点续传,也就是说,每次都会传送全部的页面和数据。
- 通常每台计算机只能绑定一个 IP,所以请求消息中的 URL 并没有传递主机名(hostname)
HTTP1.1:
- 引入了持久连接( persistent connection),即TCP连接默认不关闭,可以被多个请求复用,不用声明
Connection: keep-alive。长连接的连接时长可以通过请求头中的 keep-alive 来设置 - 引入了管道机制( pipelining),即在同一个TCP连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率
- HTTP 1.1 中新增加了 E-tag,If-Unmodified-Since, If-Match, If-None-Match 等缓存控制标头来控制缓存失效。
- 支持断点续传,通过使用请求头中的 Range 来实现。
- 使用了虚拟网络,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。
- 新增方法:PUT、PATCH、OPTIONS、DELETE。
HTTP2.0:
- 二进制分帧:这是一次彻底的二进制协议,头信息和数据体都是二进制,并且统称为"帧":头信息帧和数据帧。
之前是明文传输,不方便计算机解析,对于回车换行符来说到底是内容还是分隔符,都需
要内部状态机去识别,这样子效率低,HTTP/2采用二进制格式,全部传输01串,便于机
器解码。
- 头部压缩:HTTP 1.1版本会出现 「User-Agent、Cookie、Accept、Server、Range」 等字段可能会占用几百甚至几千字节,而 Body 却经常只有几十字节,所以导致头部偏重。HTTP 2.0 使用 HPACK 算法进行压缩。
- 多路复用:复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,且不用按顺序一一对应,这样子解决了队头阻塞的问题。
在HTTP 1.x 中,如果想并发多个请求,必须使用多个 TCP 链接,且浏览器为了控制资
源,还会对单个域名有 6-8个的TCP链接请求限制。
在HTTP2中:
1.同域名下所有通信都在单个连接上完成。
2.单个连接可以承载任意数量的双向数据流。
3.数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发
送,因为根据帧首部的流标识可以重新组装,也就是`Stream ID`,流标识符,有了它,
接收方就能从乱序的二进制帧中选择ID相同的帧,按照顺序组装成请求/响应报文。
- 服务器推送:允许服务器未经请求,主动向客户端发送资源,即服务器推送。
浏览器发送一个请求,服务器主动向浏览器推送与这个请求相关的资源,这样浏览器就不用发起后续请求。
相比较http/1.1,http/2.0的优势有:
1.推送资源可以由不同页面共享
2.服务器可以按照优先级推送资源
3.客户端可以缓存推送的资源
4.客户端可以拒收推送过来的资源
- 请求优先级:可以设置数据帧的优先级,让服务端先处理重要资源,优化用户体验。
4.HTTP1.x版本有什么问题?
- 在传输数据过程中,所有内容都是明文,客户端和服务器端都无法验证对方的身份,无法保证数据的安全性。
- HTTP/1.1 版本默认允许复用TCP连接,但是在同一个TCP连接里,所有数据通信是按次序进行的,服务器通常在处理完一个回应后,才会继续去处理下一个,这样子就会造成队头阻塞。
- HTTP/1.x 版本支持Keep-alive,用此方案来弥补创建多次连接产生的延迟,但是同样会给服务器带来压力,并且的话,对于单文件被不断请求的服务,Keep-alive会极大影响性能,因为它在文件被请求之后还保持了不必要的连接很长时间。
5.介绍一下HTTP 常见状态码
1xx: 代表请求已被接受,需要继续处理。
- 接受的请求正在处理,信息类状态码。
2xx: 表示成功状态。
- 200 OK 表示从客户端发来的请求在服务器端被正确请求。
- 204 No content,表示请求成功,但没有资源可返回。
- 206 Partial Content,该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的 GET 请求,响应报文中包含由 「Content-Range」 指定范围的实体内容。
3xx: 重定向状态。
- 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL,这时应该按 Location 首部字段提示的 URI 重新保存。
- 302 found,临时性重定向,表示资源临时被分配了新的 URL。
- 303 see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源。
- 304 not modified,当协商缓存命中时会返回这个状态码。
- 307 temporary redirect,临时重定向,和302含义相同,不会改变method
4xx: 客户端错误。
- 400 bad request,请求报文存在语法错误。
- 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息。
- 403 forbidden,表示对请求资源的访问被服务器拒绝。
- 404 not found,表示在服务器上没有找到请求的资源。
- 405 Method Not Allowed,服务器禁止使用该方法,客户端可以通过options方法来查看服务器允许的访问方法,如下
Access-Control-Allow-Methods → GET,HEAD,PUT,PATCH,POST,DELETE
5xx: 服务器端错误。
- 500 internal sever error,表示服务器端在执行请求时发生了错误。
- 502 Bad Gateway,服务器自身是正常的,访问的时候出了问题,具体啥错误我们不知道。
- 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求。
6.DNS是如何工作的
DNS 协议提供的是一种主机名到 IP 地址的转换服务,就是我们常说的域名系统。是应用层协议,通常该协议运行在UDP协议之上,使用的是43端口号。
一般而言,本地服务器查询是递归查询,而本地DNS服务器向其他域名服务器请求的过程是迭代查询的过程。
7.在DNS中,什么是递归查询、迭代查询
递归查询:指的是查询请求发出后,域名服务器代为向下一级域名服务器发出请求,最后向用户返回查询的最终结果。使用递归查询,用户只需要发出一次查询请求。
迭代查询:指的是查询请求后,域名服务器返回单次查询的结果。下一级的查询由用户自己请求。使用迭代查询,用户需要发出多次的查询请求。
8.什么是DNS缓存
在一个请求中,当某个DNS服务器收到一个DNS回答后,它能够回答中的信息缓存在本地存储器中。返回的资源记录中的 TTL 代表了该条记录的缓存的时间。
9.DNS实现负载平衡
DNS 是可以用于在冗余的服务器上实现负载平衡。这是因为一般的大型网站使用多台服务器提供服务,因此一个域名可能会对应 多个服务器地址。
- 当用户发起网站域名的 DNS 请求的时候,DNS 服务器返回这个域名所对应的服务器 IP 地址的集合
- 在每个回答中,会循环这些 IP 地址的顺序,用户一般会选择排在前面的地址发送请求。
- 以此将用户的请求均衡的分配到各个不同的服务器上,这样来实现负载均衡。
10.DNS 为什么使用 UDP 协议作为传输层协议?
DNS 使用 UDP 协议作为传输层协议的主要原因是为了避免使用 TCP 协议时造成的连接时延。
- 为了得到一个域名的 IP 地址,往往会向多个域名服务器查询,如果使用 TCP 协议,那么每次请求都会存在连接时延,这样使 DNS 服务变得很慢。
- 大多数的地址查询请求,都是浏览器请求页面时发出的,这样会造成网页的等待时间过长。
11.什么是Connection:keep-alive
HTTP协议采用“请求-应答”模式,当使用普通模式,即非KeepAlive模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP协议为无连接的协议);
当使用Keep-Alive模式(又称持久连接、连接重用)时,Keep-Alive功能使客户端到服 务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
12.为什么要使用keep-alive
keep-alive技术的创建目的,能在多次HTTP之前重用同一个TCP连接,从而减少创建/关闭多个 TCP 连接的开销(包括响应时间、CPU 资源、减少拥堵等),参考如下示意图
13.什么是HTTP强缓存
强缓存就是当浏览器判断出本地缓存未过期时,直接读取本地缓存,无须发起HTTP请求,此时状态为 200 from cache,在HTTP1.1版本后通过头部的cache-control字段的max-age属性值规定的过期时长来判断缓存是否过期失效,这比使用HTTP1.0版本expires标识的服务器过期时间更准确且安全。
Expires
Expires即过期时间,时间是相对于服务器的时间而言的,存在于服务端返回的响应头中,在这个过期时间之前可以直接从缓存里面获取数据,无需再次请求。比如下面这样:
Expires:Mon, 29 Jun 2020 11:10:23 GMT
表示该资源在2020年7月29日11:10:23过期,过期时就会重新向服务器发起请求。
这个方式有一个问题:服务器的时间和浏览器的时间可能并不一致,所以HTTP1.1提出新的字段代替它。
Cache-Control
HTTP1.1版本中,使用的就是该字段,这个字段采用的时间是过期时长,对应的是max-age。
Cache-Control:max-age=6000
上面代表该资源返回后6000秒,可以直接使用缓存。
注意点:
- 当Expires和Cache-Control同时存在时,优先考虑Cache-Control。
- 当缓存资源失效了,也就是没有命中强缓存,接下来就进入协商缓存。
14.什么是协商缓存
协商缓存则需要浏览器向服务器发起HTTP请求,来判断浏览器本地缓存的文件是否仍未修改,若未修改则从缓存中读取,此时的状态为304,具体过程是判断浏览器头部if-none-match与服务器端的e-tag是否匹配,来判断所访问的数据是否发生更改。这相比HTTP1.0版本通过last-modified判断上次文件修改时间来说也更加准确。
Last-Modified
这个字段表示的是「最后修改时间」。在浏览器第一次给服务器发送请求后,服务器会在响应头中加上这个字段。
浏览器接收到后,「如果再次请求」,会在请求头中携带If-Modified-Since字段,这个字段的值也就是服务器传来的最后修改时间。
服务器拿到请求头中的If-Modified-Since的字段后,其实会和这个服务器中该资源的最后修改时间对比:
- 如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。
- 否则返回304,告诉浏览器直接使用缓存。
ETag
ETag是服务器根据当前文件的内容,对文件生成唯一的标识,比如MD5算法,只要里面的内容有改动,这个值就会修改,服务器通过把响应头把该字段给浏览器。
浏览器接受到ETag值,会在下次请求的时候,将这个值作为「If-None-Match」这个字段的内容,发给服务器。
服务器接收到「If-None-Match」后,会跟服务器上该资源的「ETag」进行比对
- 如果两者一样的话,直接返回304,告诉浏览器直接使用缓存
- 如果不一样的话,说明内容更新了,返回新的资源,跟常规的HTTP请求响应的流程一样
15.协商缓存中,Last-Modified和ETag的区别是什么
- 性能上,Last-Modified优于ETag,Last-Modified记录的是时间点,而Etag需要根据文件的MD5算法生成对应的hash值。
- 精度上,ETag优于Last-Modified。ETag按照内容给资源带上标识,能准确感知资源变化,Last-Modified在某些场景并不能准确感知变化,比如
编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。
Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的Last-Modified 并没有体现出修改了。
最后,「如果两种方式都支持的话,服务器会优先考虑ETag」。
16.HTPP缓存的位置在哪里
浏览器缓存的位置的话,可以分为四种,优先级从高到低排列分别:
- Service Worker:这个应用场景比如PWA,它借鉴了Web Worker思路,由于它脱离了浏览器的窗体,因此无法直接访问DOM。它能完成的功能比如:离线缓存、消息推送和网络代理,其中离线缓存就是「Service Worker Cache」
- Memory Cache:指的是内存缓存,从效率上讲它是最快的,从存活时间来讲又是最短的,当渲染进程结束后,内存缓存也就不存在了。
- Disk Cache:存储在磁盘中的缓存,从存取效率上讲是比内存缓存慢的,优势在于存储容量和存储时长。
- Push Cache:推送缓存,这算是浏览器中最后一道防线吧,它是HTTP/2的内容。
17.说一说HTTP的请求方法
HTTP1.0定义了三种请求方法:
- GET:请求获取Request-URI所标识的资源
- POST:在Request-URI所标识的资源后附加新的数据
- HEAD:请求获取由Request-URI所标识的资源的响应消息报头
HTTP1.1新增了五种请求方法:
- PUT:请求服务器存储一个资源,并用Request-URI作为其标识(修改数据)
- DELETE:请求服务器删除对应所标识的资源
- TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断
- CONNECT:建立连接隧道,用于代理服务器
- OPTIONS:列出可对资源实行的请求方法,用来跨域请求
18.谈一谈GET和POST的区别
本质上,只是语义上的区别,GET 用于获取资源,POST 用于提交资源。具体差别:
- 从缓存角度看,GET 请求后浏览器会主动缓存,POST 默认情况下不能。
- 从参数角度来看,GET请求一般放在URL中,因此不安全,POST请求放在请求体中,相对而言较为安全,但是在抓包的情况下都是一样的。
- 从编码角度看,GET请求只能经行URL编码,只能接受ASCII码,而POST支持更多的编码类型且不对数据类型限值。
- GET请求幂等,POST请求不幂等,幂等指发送 M 和 N 次请求(两者不相同且都大于1),服务器上资源的状态一致。
- GET请求会一次性发送请求报文,POST请求通常分为两个TCP数据包,首先发 header 部分,如果服务器响应 100(continue), 然后发 body 部分。
- 从应用场景角度来看,Get 多用于无副作用,幂等的场景,例如搜索关键字。Post 多用于副作用,不幂等的场景,例如注册。
19.什么是队头阻塞问题?有什么解决办法吗
对于每一个HTTP请求而言,这些任务是会被放入一个任务队列中串行执行的,一旦队首任务请求太慢时,就会阻塞后面的请求处理,这就是HTTP队头阻塞问题。
解决办法
- (1)并发连接:我们知道对于一个域名而言,是允许分配多个长连接的,那么可以理解成增加了任务队列,也就是说不会导致一个任务阻塞了该任务队列的其他任务,在RFC规范中规定客户端最多并发2个连接,不过实际情况就是要比这个还要多,举个例子,Chrome中是6个。
- (2)域名分片:顾名思义,我们可以在一个域名下分出多个二级域名出来,而它们最终指向的还是同一个服务器,这样子的话就可以并发处理的任务队列更多,也更好的解决了队头阻塞的问题。
20.介绍一下HTTPS和HTTP区别
HTTPS 要比 HTTPS 多了 secure 安全性这个概念,实际上, HTTPS 并不是一个新的应用层协议,它其实就是 HTTP + TLS/SSL 协议组合而成,而安全性的保证正是 SSL/TLS 所做的工作。
- SSL:安全套接层(Secure Sockets Layer)
- TLS:传输层安全(Transport Layer Security)
HTTP和HTTPS的区别:
- HTTP 是明文传输协议,HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全。
- HTTPS比HTTP更加安全,对搜索引擎更友好,利于SEO谷,歌、百度会优先索引HTTPS网页。
- HTTPS标准端口443,HTTP标准端口80。
- HTTPS需要用到SSL证书,而HTTP不用。
HTTPS主要的作用就是:
- 对数据进行加密,并建立一个信息安全通道,来保证传输过程中的数据安全;
- 对网站服务器进行真实身份认证。
21.TLS/SSL的功能是怎么实现的
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
22.什么是对称加密
加密和解密用同一个秘钥的加密方式叫做对称加密。Client客户端和Server端共用一套密钥,这样子的加密过程似乎很让人理解,但是随之会产生一些问题。
- 问题一:WWW万维网有许许多多的客户端,不可能都用秘钥A进行信息加密,这样子很不合理,所以解决办法就是使用一个客户端使用一个密钥进行加密。
- 问题二:既然不同的客户端使用不同的密钥,那么对称加密的密钥如何传输?解决的办法只能是一端生成一个秘钥,然后通过HTTP传输给另一端,那么这样子又会产生新的问题。
- 问题三:这个传输密钥的过程,又如何保证加密?如果被中间人拦截,密钥也会被获取,那么你会说对密钥再进行加密,那又怎么保存对密钥加密的过程,是加密的过程?
到这里,我们应该能想明白,使用对称加密的方式,行不通,所以我们需要采用非对称加密。
23.什么是非对称加密
非对称加密采用的算法是RSA,所以在一些文章中也会看见传统RSA握手,基于现在TLS主流版本是1.2,所以接下来梳理的是TLS/1.2握手过程。
非对称加密中,我们需要明确几点:
- 有一对秘钥,
公钥和私钥。 - 公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开,这里说的
公钥都可以解开,指的是一对秘钥。 - 公钥可以发送给所有的客户端,私钥只保存在服务器端。
24.非对称加密也就是TLS1.2握手的过程是怎样的?
- (1)Client发起一个HTTPS请求,连接443端口。这个过程可以理解成是请求公钥的过程。
- (2)Server端收到请求后,通过第三方机构私钥加密,会把数字证书(也可以认为是公钥证书)发送给Client。
- (3)浏览器安装后会自动带一些权威第三方机构公钥,使用匹配的公钥对数字签名进行解密;根据签名生成的规则对网站信息进行本地签名生成,然后两者比对;通过比对两者签名,匹配则说明认证通过,不匹配则获取证书失败。
- (4)在安全拿到「服务器公钥」后,客户端Client随机生成一个「对称密钥」,使用「服务器公钥」(证书的公钥)加密这个「对称密钥」,发送给Server(服务器)。
- (5)Server(服务器)通过自己的私钥,对信息解密,至此得到了「对称密钥」,此时两者都拥有了相同的「对称密钥」。接下来,就可以通过该对称密钥对传输的信息加密/解密啦,举个例子
Client用户使用该「对称密钥」加密'明文内容B',发送给Server(服务器)
Server使用该「对称密钥」进行解密消息,得到明文内容B。
25.客户端可能拿到的公钥是假的,解决办法是什么呢?
客户端无法识别传回公钥是中间人的,还是服务器的,这是问题的根本,我们是不是可以通过某种规范可以让客户端和服务器都遵循某种约定呢?那就是通过「第三方认证的方式」
在HTTPS中,通过 「证书」 + 「数字签名」来解决这个问题。
我们再次假设中间人截取到服务器的公钥后,去替换成自己的公钥,因为有数字签名的存在,这样子客户端验证发现数字签名不匹配,这样子就防止中间人替换公钥的问题。
那么客户端是如何去对比两者数字签名的呢?
- 浏览器会去安装一些比较权威的第三方认证机构的公钥,比如VeriSign、Symantec以及GlobalSign等等。
- 验证数字签名的时候,会直接从本地拿到相应的第三方的公钥,对私钥加密后的数字签名进行解密得到真正的签名。
- 然后客户端利用签名生成规则进行签名生成,看两个签名是否匹配,如果匹配认证通过,不匹配则获取证书失败。
25.谈一谈对URL的理解
URL是统一资源定位符(Uniform Resource Locator)的简称,常常被称为网址,是因特网上标准的资源地址。
它的通用格式为:scheme://host[:port]/path/…/?query#anchor
- scheme:访问服务器以获取资源时要使用哪种协议,比如:HTTP,HTTPS 和 FTP 等
- host:HTTP 服务器的 IP 地址或者域名
- port:HTTP 服务器的默认端口是 80,HTTPS默认端口是443,这种情况下端口号可以省略,如果使用了别的端口,必须指明。不同的端口,你可以认为是不同的应用程序。
- path:访问资源的路径
- query-string:发给http服务器的数据
- anchor:锚点
https://www.baidu.com/s?tn=baidu&bar=&wd=TianTian
26.什么是正向代理
我们常说的代理也就是指正向代理,正向代理的过程,它隐藏了真实的请求客户端,服务端不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替来请求。
27.什么是反向代理
这种代理模式下,它隐藏了真实的服务端,当我们向一个网站发起请求的时候,背后可能有成千上万台服务器为我们服务,具体是哪一台,我们不清楚,我们只需要知道反向代理服务器是谁就行,而且反向代理服务器会帮我们把请求转发到真实的服务器那里去,一般而言反向代理服务器一般用来实现负载平衡。
28.负载均衡的两种实现方式是什么
- 一种是使用反向代理的方式,用户的请求都发送到反向代理服务上,然后由反向代理服务器来转发请求到真实的服务器上,以此来实现集群的负载平衡。
- 另一种是 DNS 的方式,DNS 可以用于在冗余的服务器上实现负载平衡。因为现在一般的大型网站使用多台服务器提供服务,因此一个域名可能会对应多个服务器地址。当用户向网站域名请求的时候,DNS 服务器返回这个域名所对应的服务器 IP 地址的集合,但在每个回答中,会循环这些 IP 地址的顺序,用户一般会选择排在前面的地址发送请求。以此将用户的请求均衡的分配到各个不同的服务器上,这样来实现负载均衡。这种方式有一个缺点就是,由于 DNS 服务器中存在缓存,所以有可能一个服务器出现故障后,域名解析仍然返回的是那个 IP 地址,就会造成访问的问题。
29.HTTP可以拆解成哪4部分
- server:服务端,返回响应
- client:客户端,发起请求
- request
- response
30.request请求报文包含哪4部分
- 请求行:动词(GET/POST) 路径(带查询字符串) 协议/版本号(HTTP/1.1这样的)
- 请求头:一堆 key: value(value前有空格 )
- 回车:作用只有一个,分离第二部分和第四部分
- 请求体:Body 随便什么内容都可以,但是内容的格式需要在第二部分当中的Contet-type 当中
31.response响应报文包含哪4部分
- 响应行:协议/版本号(HTTP/1.1这样的) 状态码 状态信息
- 响应头:一堆 key: value(value前有空格 )
- 回车:作用只有一个,分离第二部分和第四部分
- 响应体:Body 随便什么内容都可以,但是内容的格式需要在第二部分当中的Contet-type 当中
32.什么是TCP协议
TCP/IP协议是一个协议簇。里面包括很多协议的,UDP只是其中的一个,之所以命名为TCP/IP协议,因为TCP、IP协议是两个很重要的协议,就用他两命名了。
TCP(Transmission Control Protocol,传输控制协议)是面向连接的协议,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,只简单的描述下这三次对话的过程:
- (1)主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;
- (2)主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;
- (3)主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。
三次“对话”的目的是使数据包的发送和接收同步, 经过三次“对话”之后,主机A才向主机B正式发送数据。
33.具体描述下TCP三次握手过程
- 第一次握手:主机A通过向主机B 发送一个含有同步序列号的标志位的数据段给主机B,向主机B 请求建立连接,通过这个数据段,主机A告诉主机B 两件事:我想要和你通信;你可以用哪个序列号作为起始数据段来回应我。
- 第二次握手:主机B 收到主机A的请求后,用一个带有确认应答(ACK)和同步序列号(SYN)标志位的数据段响应主机A,也告诉主机A两件事:我已经收到你的请求了,你可以传输数据了;你要用那个序列号作为起始数据段来回应我
- 第三次握手:主机A收到这个数据段后,再发送一个确认应答,确认已收到主机B 的数据段:"我已收到回复,我现在要开始传输实际数据了,这样3次握手就完成了,主机A和主机B 就可以传输数据了。
34.TCP三次握手的特点是什么
没有应用层的数据,SYN这个标志位只有在TCP建立连接时才会被置1,握手完成后SYN标志位被置0。
35.为什么三次握手建立连接的TCP客户端最后还要发送一次确认呢?
主要是防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
36.具体描述描述下TCP四次挥手过程
- 第一次挥手:当主机A完成数据传输后,将控制位FIN置1,提出停止TCP连接的请求;
- 第二次挥手:主机B收到FIN后对其作出响应,确认这一方向上的TCP连接将关闭,将ACK置1;
- 第三次挥手:由B端再提出反方向的关闭请求,将FIN置1;
- 第四次挥手:主机A对主机B的请求进行确认,将ACK置1,双方向的关闭结束。
由TCP的三次握手和四次断开可以看出,TCP使用面向连接的通信方式,大大提高了数据通信的可靠性,使发送数据端和接收端在数据正式传输前就有了交互,为数据正式传输打下了可靠的基础。
37.为什么建立连接是三次握手,关闭连接却是四次挥手呢?
- 建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
- 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了,但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
38.什么是UDP协议
- UDP(User Data Protocol,用户数据报协议)是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。在发送端,UDP传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制;在接收端,UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。
- 由于传输数据不建立连接,因此也就不需要维护连接状态,包括收发状态等,因此一台服务机可同时向多个客户机传输相同的消息。
- UDP信息包的标题很短,只有8个字节,相对于TCP的20个字节信息包的额外开销很小。
- 吞吐量不受拥挤控制算法的调节,只受应用软件生成数据的速率、传输带宽、源端和终端主机性能的限制。
- UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态表(这里面有许多参数)。
- UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层。既不拆分,也不合并,而是保留这些报文的边界, 因此,应用程序需要选择合适的报文大小。
39.TCP协议和UDP协议的区别是什么
- (1)基于连接与无连接;
- (2)对系统资源的要求(TCP较多,UDP少);
- (3)UDP程序结构较简单;
- (4)流模式与数据报模式;
- (5)TCP保证数据正确性,UDP可能丢包;
- (6)TCP保证数据顺序,UDP不保证。
40.HTTP定长数据传输
对于定长的数据包而言,发送端在发送数据的过程中,需要设置Content-Length,来指明发送数据的长度。如果采用了Gzip压缩的话,Content-Length设置的就是压缩后的传输长度。
需要知道的是:
- Content-Length如果存在并且有效的话,则必须和消息内容的传输长度完全一致,也就是说,如果过短就会截断,过长的话,就会导致超时。
- 如果采用短链接的话,直接可以通过服务器关闭连接来确定消息的传输长度。
- 那么在HTTP/1.0之前的版本中,Content-Length字段可有可无,因为一旦服务器关闭连接,我们就可以获取到传输数据的长度了。
- 在HTTP/1.1版本中,如果是Keep-alive的话,chunked优先级高于
Content-Length,若是非Keep-alive,跟前面情况一样,Content-Length可有可无。
设置Content-Length:
const server = require('http').createServer()
server.on('request', (req, res) => {
if (req.url === '/index') {
// 设置数据类型
res.setHeader('Content-Type', 'text/plain')
res.setHeader('Content-Length', 10)
res.write('你好,使用的是Content-Length设置传输数据形式')
}
})
server.listen(3000, () => {
console.log('成功启动--TinaTian')
})
41.HTTP不定长数据传输
现在采用最多的就是HTTP/1.1版本,来完成传输数据,在保存Keep-alive状态下,当数据是不定长的时候,我们需要设置新的头部字段Transfer-Encoding: chunked
通过chunked机制,可以完成对不定长数据的处理,当然了,需要知道的是:
- 如果头部信息中有
Transfer-Encoding,优先采用Transfer-Encoding里面的方法来找到对应的长度。 - 如果设置了
Transfer-Encoding,那么Content-Length将被忽视。 - 使用长连接的话,会持续的推送动态内容。
模拟实现:
const server = require('http').createServer()
server.on('request', (req, res) => {
if (req.url === '/index') {
// 设置数据类型
res.setHeader('Content-Type', 'text/html; charset=utf8')
res.setHeader('Content-Length', 10)
res.setHeader('Transfer-Encoding', 'chunked')
res.write('你好,使用的是Transfer-Encoding设置传输数据形式')
setTimeout(() => {
res.write('第一次传输数据给您<br/>')
}, 1000)
res.write('骚等一下')
setTimeout(() => {
res.write('第一次传输数据给您')
res.end()
}, 3000)
}
})
server.listen(3000, () => {
console.log('成功启动--TinaTian')
})