计算机面试重难点之计算机网络
TCP(传输层)
TCP报文段头部
每个 TCP 段都包含源端和目的端的端口号,用于寻找发送方和接收方应用进程。这两个值加 上 IP 首部中的源端 IP 地址和目的端 IP 地址唯一确定一个 TCP 连接。
首部固定部分各字段意义如下:
-
源端口和目的端口:各占 2 个字节,分别写入源端口和目的端口。
IP 地址 + 端口号
就可以确定一台主机的一个进程地址 -
序号/序列号(Sequense Number,SN):在一个 TCP 连接中传送的字节流中的每一个字节都按顺序编号。该字段表示本报文段所发送的数据的第一个字节的序号。初始序号称为 Init Sequense Number, ISN(专指TCP三次握手时前两次握手的报文段中的序号)。
例如,一报文段的序号是 101,共有 100 字节的数据。这就表明:本报文段的数据的第一个字节的序号是 101,最后一个字节的序号是 200。显然,下一个报文段的数据序号应当从 201 开始,即下一个报文段的序号字段值应为 201。
-
确认号 ack:期望收到对方下一个报文段的第一个数据字节的序号。若确认号为
N
,则表明:到序号N-1
为止的所有数据都已正确收到。 -
数据偏移(首部长度):它指出
TCP
报文段的数据起始处距离TCP
报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。 -
保留:占 6 位,应置为 0,保留为今后使用。
6 个控制位非常重要:
-
紧急位 URG:当
URG = 1
时,表明此报文段中有紧急数据,是高优先级的数据,应尽快发送,不用在缓存中排队。该控制位需配合紧急指针使用。举个例子:我们需要取消一个已经发送了很长程序的运行,因此用户从键盘发出中断命令。如果不使用紧急数据,那么这个指令将存储在接收 TCP 的缓存末尾,只有在所有的数据被处理完毕后这两个字符才被交付接收方的应用进程,这样做就无法实现立即中断。
-
确认 ACK:仅当
ACK = 1
时确认号字段才有效,当ACK = 0
时确认号无效。TCP
规定,在连接建立后所有传送的报文段都必须把ACK
置为 1。 -
推送 PSH:接收方收到
PSH = 1
的报文段,就尽快地交付到上层应用进程。而不用等到整个缓存都填满了后再向上交付。当两个应用进程进行交互式的通信时,有时发送方的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,发送方可以创建一个报文段并把PSH 置为 1
发送出去。 -
复位 RST:当
RST = 1
时,表明TCP
连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。 -
同步 SYN:
SYN = 1
表示这是一个连接请求
或连接确认
报文段。当SYN = 1
而ACK = 0
时,表明这是一个连接请求
报文段。对方若同意建立连接,则应在响应的连接确认
报文段中使SYN = 1
且ACK = 1
。 -
终止 FIN:用来释放一个连接。当
FIN = 1
时,表明此报文段的发送方数据已发送完毕,并要求释放TCP
连接。 -
窗口:用于流量控制,指明双方的窗口大小。
-
校验和:发送方初始校验和字段为0,对
TCP 首部
(包含12字节的伪首部)和TCP 数据
每个16 bit
进行二进制反码的求和,然后重新填入校验和字段。接收方收到数据后以同样的方式计算校验和,但接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果传输过程中没有发生任何差错, 那么接收方计算的校验和结果应该为全1。举例:假设发送方计算的校验和为
10101010
。如果传输无误,那么接收方收到时,不包含校验和字段计算的反码求和应该为10101010
,再加上校验和字段的反码(01010101
)即为最终的校验和:11111111
。 -
紧急指针:当
URG = 1
时,该字段才有效。关于紧急指针是指向紧急数据的最后一个字节还是指向紧急数据最后一个字节的下一个字节的争论。最初的TCP
规范给出了两种解释,但Host Requirements RFC
确定指向最后一个字节是正确的。然而,问题在于大多数的实现(包括源自伯克利的实现)继续使用错误的解释。所有符合Host Requirements RFC
的实现都是可兼容的,但很有可能无法与其他大多数主机正确通信。
三次握手过程
三次握手(Three-way Handshake)指客户端和服务器建立一个TCP连接时,双方总共需要发送3个报文段。目的:确认双方的接收能力和发送能力是否正常
;同时指定双方的初始化序列号(ISN)为后面的可靠性传送做准备
。
刚开始服务端处于监听状态,进行三次握手由客户端主动发起:
-
第一次握手:客户端给服务端发一个
连接请求报文段
,头部指明SYN=1
,ACK=0
以及初始化序列号ISN
(seq=x
)。此报文段不能携带数据,但要消耗掉一个序号。随后客户端进入SYN_SENT
(同步发送)状态。 -
第二次握手:服务端收到客户端的
连接请求报文段
之后,向客户端发送连接确认报文段
,头部指明SYN=1
,ACK=1
,确认号(ack
)为x+1
,并且也选择一个初始化序列号y
。随后服务器进入SYN_RCVD
(同步接收)的状态。 -
第三次握手:客户端收到服务端的
连接确认报文段
之后,会向服务端回送一个确认报文段
,头部指明ACK=1
,确认号ack=y+1
,序号seq=x+1
,该报文段可以携带数据,不携带数据则不消耗序号。随后客户端进入ESTABLISHED
(连接已建立)状态。待服务器收到客户端发送的ACK
报文段也会进入ESTABLISHED
状态,完成三次握手。
三次握手为什么不能是两次?
-
首先需要明确:三次握手是为了让客户端和服务端确认对方的发送能力以及接受能力都是正常的。
第一次握手:客户端发送报文段,服务端收到了。
这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。第二次握手:服务端发送报文段,客户端收到了。
这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。第三次握手:客户端发送报文段,服务端收到了。
这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。因此,改成两次握手,服务端不能确定发送端的接收能力是否正常。
-
且可能存在以下情况:客户端向服务端发送
连接请求报文段
,但由于网络原因滞留在网络中。客户端超时重传了一个新的连接请求报文段
,利用新的请求客户端和服务端成功建立连接并通信,通信完后关闭释放了连接。但此时旧的(失效的)连接请求报文段
重新到达服务端,如果采用两次握手建立连接那么就会导致服务端建立错误的连接。 -
其次两次握手,就建立连接,会放大
DDOS
攻击。
什么是半连接队列
服务器第一次收到客户端的连接请求报文段
之后,就会处于SYN_RCVD
(同步接收) 状态,此时双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,我们把这种队列称之为半连接队列。
当然还有一个全连接队列,就是已经完成三次握手,建立起连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
ISN
(Initial Sequence Number)是固定的吗?
TCP建立连接时会确定客户端和服务端的ISN
并交换,他们是后序所发送字节数据编号的原点。ISN
是通过随机生成算法生成的,如果ISN
是固定的,攻击者很容易猜出后续的确认号,因此 ISN
是动态生成的。此外,如果相同客户端和服务端的前后两次连接的ISN
的相同,第一次连接结束后,第二次连接数据传输过程中,属于前一次连接但滞留在网络中的报文段突然又到达服务端,服务器是没法区分的。
备注:RFC1948
中提出了一个较好的初始化序列号ISN
随机生成算法。ISN = M + F(localhost, localport, remotehost, remoteport)
。M
是一个计时器,这个计时器每隔4毫秒加1。F
是一个Hash
算法,根据源IP
、目的IP
、源端口
、目的端口
生成一个随机数值。要保证hash算法不能被外部轻易推算得出,用MD5
算法是一个比较好的选择。
三次握手过程中可以携带数据吗?
第一次、第二次握手不可以携带数据,而第三次握手是可以携带数据的。
假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 连接请求报文段
中放入大量的数据,并疯狂重发。这会让服务器花费大量的内存空间来缓存这些报文段,这样服务器就更容易被攻击了。
对于第三次握手,此时客户端已经处于连接状态,他已经知道服务器的接收、发送能力是正常的了,所以可以携带数据是情理之中。
SYN攻击是什么?
SYN
攻击是一种典型的 DoS/DDoS(Distributed Denial of Service)
攻击,攻击方利用服务器端的资源是在二次握手时分配的这一特征进行攻击。SYN
攻击就是攻击端在短时间内伪造大量不存在的IP地址
,并向服务端不断地发送连接请求报文段
,服务端则回复连接确认报文段
,并等待攻击端的确认报文段
,由于源地址是伪造的,因此服务端需要不断重发直至超时,这些伪造的连接请求报文段
导致大量的请求连接
长时间占用半连接队列
,导致正常的请求连接
因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。
第三次握手失败怎么办?
客户端收到服务端的连接确认报文段
后,其状态变为ESTABLISHED
,并会发送确认报文段
给服务端,准备发送数据了。如果此时确认报文段
在网络中丢失,并且超时,那么服务端会重新发送连接确认报文段
。如果重传指定次数之后仍然未收到客户端的确认报文段
,服务端将自动关闭这个连接。但是客户端认为这个连接已经建立,如果客户端向服务端发数据,服务端将以复位报文段
响应,客户端方能感知到服务端的错误。
四次挥手过程
四次挥手(Four-way handshake)指主动方和和被动方断开 TCP
连接需要发送四个包,客户端或服务端均可主动发起挥手动作。
挥手前,双方都处于ESTABLISHED
状态,假如是客户端先发起关闭请求,对应过程如下:
- 第一次挥手:客户端向服务端发送一个
连接释放报文段
,头部指明FIN=1
,序号seq=u
。并停止发送数据,主动关闭TCP
连接。随后客户端进入FIN_WAIT1
(终止等待1)状态,等待服务端的确认。 - 第二次挥手:服务端收到客户端发来的
连接释放报文段
后,回送确认报文段
,头部指明ACK=1
,确认号ack=u+1
,序号seq=v
,随后服务端进入CLOSE_WAIT
(关闭等待) 状态。客户端收到服务端的确认报文段
后,进入FIN_WAIT2
(终止等待2)状态,等待服务端发出的连接释放报文段
。 - 第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一样,向客户端发送
连接释放报文段
,头部指明FIN=1
,ACK=1
,序号seq=w
,确认号ack=u+1
,随后服务端进入LAST_ACK
(最后确认)状态,等待客户端的确认报文段
。 - 第四次挥手:客户端收到
连接释放报文段
之后,同样向服务端发出确认报文段
,头部指明ACK=1
,seq=u+1
,ack=w+1
,此时客户端进入TIME_WAIT
状态。服务端收到客户端的确认报文段
之后,进入CLOSED
状态。客户端必须经过2*MSL
后才进入CLOSED
状态。此时TCP
连接已经完全释放。
建立连接只需要握手三次,关闭连接时需要挥手四次呢?
其实在 TCP
第二次握手的时候,服务端发送的 连接确认报文段
将一个 ACK
和一个 SYN
合并到一起发送给服务端,所以减少了一次包的发送,三次便完成握手。对于四次挥手,因为 TCP
是全双工通信,在主动方发送连接释放报文段
后,被动方可能还要发送数据,不能立即关闭被动方到主动方的数据通道,所以被动方不能将确认报文段
与 连接释放报文段
合并回送给主动方。只能先发送将确认报文段
回送给主动方,然后待被动方无需发送数据时再回送 连接释放报文段
,所以四次挥手必须使用四次数据包交互。
四次挥手时,主动方等待2MSL的意义?
MSL是
Maximum Segment Lifetime
的英文缩写,指“报文段在网络中最大生存时间”,超过这个时间报文段将被丢弃。
-
保证主动方发送的最后一个
确认报文段
能够到达被动方。这个
确认报文段
有可能丢失,使得处于LAST-ACK
(最后确认)状态的被动方收不到该报文段,被动方超时重传连接释放报文段
,而主动方能在2MSL
时间内收到这个重传的连接释放报文段
,接着主动方重传一次确认报文段
,重启2MSL
计时器,最后双方都进入到CLOSED
状态。若主动方发完确认报文段
后立即释放连接,被动方在超时未收到确认报文段
的情况就不能正常处理,就导致被动方无法正常进入到CLOSED
状态。 -
防止“已失效的连接请求报文段”出现在本连接中。
主动方发送完最后一个
确认报文段
,再经过2MSL
,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
其他
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP
设有一个保活计时器,服务器每收到一次客户端的TCP报文段
后都会重新复位这个计时器,时间通常是设置为2小时。客户端如果出现故障若,导致服务端两小时都没有收到客户端的任何数据,服务器就会每隔75秒钟发送一个探测报文段,若一连发送10个探测报文段仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
TCP依靠哪些机制来保证可靠传输?
-
校验和:
TCP
通过校验和检测数据在传输过程中是否发生改变,如果收到的报文段的校验和有差错,报文段将被丢弃。 -
序列号和确认应答:
TCP
给发送的每一个报文段中都有序号字段,每次接收方收到数据后,都会对传输方进行确认应答,即发送确认报文段(ACK)
,其中的确认号告诉发送方成功接收了哪些数据以及下一次的数据从哪里开始发。除此之外,接收方可以根据序列号对数据包进行排序,把有序数据传送给应用层,并丢弃重复的数据。 -
超时重传:当
TCP
发出一个报文段后,它将启动一个定时器,等待接收端发回的确认。如果超过定时器超时还没有收到确认,发送方将重发这个报文段。 -
约定最大报文段长度(MSS):在建立
TCP
连接的时候,双方约定最大报文段长度作为发送的单位,理想的情况下是该长度的数据刚好不被网络层分片。 -
流量控制:
TCP
通过滑动窗口机制实现流量控制,窗口(缓冲区)的大小就是发送方在无需等待确认报文段
的情况下还能发送的最大数据量。TCP
通过窗口大小来协调端对端的发送速度,确保接收端来得及接收,从而尽可能减少丢包。 -
拥塞控制:通过拥塞控制算法(慢开始、拥塞避免、快重传、快恢复),根据全局网络的拥塞程度来调整拥塞窗口的大小,改善网络拥塞程度,从而尽可能减少丢包。
备注:发送窗口的大小等于Min(接收窗口, 拥塞窗口),因此是两种流量控制和拥塞控制的共同作用。
ARQ协议与滑动窗口机制的关系?
自动重传请求 ( Automatic Repeat-reQuest , ARQ
)是 OSI
模型 中 数据链路层 和 传输层 的错误纠正协议之一。其利用确认和超时这两个机制,可以在不可靠服务的基础上实现可靠的信息传输。ARQ
协议分等停ARQ协议
和连续ARQ
协议,连续ARQ
协议采用了滑动窗口机制,后者又可分为后退N步协议
和选择重传协议
。
拥塞控制有哪些算法?
拥塞控制算法:慢开始、拥塞避免、快重传、快恢复。这些算法会根据网络不同的拥塞状况来搭配使用。
慢开始算法:在一开始不清楚网络拥塞程度时,避免一开始就向网络中注入大量数据,由小到大逐渐增大拥塞窗口数值。cwnd
(拥塞窗口) 初始值设为为 1,每经过一个传输轮次(transmission round
),cwnd
加倍。(慢开始并不是指cwnd增长慢)。当拥塞窗口达到慢开始门限值 ssthresh
,改用拥塞避免算法。(当cwnd = ssthresh
时,既可使用慢开始算法,也可使用拥塞避免算法)。
拥塞避免算法: 拥塞避免算法的思路是让 cwnd
缓慢地增大,即每经过一个往返时间 RTT
就把发送方的拥塞窗口 cwnd
加1,而不是加倍。这样,拥塞窗口 cwnd
按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。
无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(计时器超时,未收到确认),就要把慢开始门限 ssthresh
设置为出现拥塞时的发送窗口值的一半(但不能小于2)。然后把拥塞窗口 cwnd 重新设置为 1,执行慢开始算法。
快重传算法:快重传算法要求接收方在收到一个失序的报文段后就立即发出重复确认
而不要等到自己发送数据时捎带确认。发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。(以便发送方及早知道丢失发生,及早进行重传)。与快重传配合使用的还有快恢复算法。
快恢复算法:当发送方连续收到三个重复确认时,把 ssthresh
门限减半。考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方认为现在网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd
设置为ssthresh
的大小,然后执行拥塞避免算法。
流量控制与拥塞控制有何不同?
流量控制:采用端对端的机制,接收端通过窗口字段告知发送端自己的接收能力,进而协调发送端的发送速度,避免接收端来不及接收而丢包。
拥塞控制:采用面向全局的机制,根据网络的拥塞程度来改变拥塞窗口,进而协调主机向网络中注入数据的速度,改善网络拥塞程度,从而尽可能减少丢包。
TCP 和 UDP 的区别?
类型 | 传输可靠性 | 是否面向连接 | 是否支持多播,广播 | 传输形式 | 资源占用 | 首部长度(字节) | 应用场景 |
---|---|---|---|---|---|---|---|
TCP | 可靠 | 是 | 否 | 面向字节流 | 多 | 20 – 60 | 文件,邮件传输 |
UDP | 不可靠 | 否 | 是 | 面向报文段 | 少 | 8 | 即时通讯,直播等 |
TCP
提供可靠服务,在传送数据之前必须先建立连接,数据传送结束后要释放连接;UDP
与之相反,只尽最大努力交付。
TCP
不提供广播或多播服务;UDP
则提供。
TCP
是面向字节流的;而UDP
是面向报文段的。
TCP
要提供可靠的服务,建立连接,释放连接,加之确认、窗口、重传、流量控制、拥塞控制、定时器等机制都会占用更多的系统资源,同时导致协议头部增大(20 – 60 字节);UDP
则占用较少系统资源,协议头部也更小(仅 8 字节)。
TCP
提供可靠服务,故使用在文件传输、邮件传输等场景;虽然 UDP
不提供可靠交付,但在某些情况下 UDP
确是一种最有效的工作方式,如即时通讯,直播等场景。
什么是 TCP 粘包问题?
TCP
粘包就是指发送方应用层交给TCP
发送的若干数据包经过TCP
传输到达接收方时合并粘成了一个数据包,出现粘包的原因是多方面的,可能是来自发送方,也可能是来自接收方。
造成TCP粘包的原因?
-
发送方原因
TCP
默认使用Nagle
算法,当应用层交付给TCP
发送的数据包过于小时,发送方会收集了多个较小的数据包进行合并发送,这将会发生粘包。 -
接收方原因
TCP
发送方发送数据很快,接收方TCP
缓冲区收到大量数据,但应用层取出数据的速度又太慢,造成多个数据包被缓存,应用层就有可能读取到多个首尾相接粘到一起的数据包。
什么时候需要处理粘包问题?
- 如果发送方发送的多个数据包本来就是同一块数据的不同部分就不需要处理粘包现象。
- 如果多个数据包毫不相干,甚至是并列关系,那么这个时候就一定要处理粘包现象了。
如何处理粘包问题?
在应用层进行处理。如:
- 在应用层交给
TCP
的每个数据包头部都添加长度字段,接收方应用层读取数据时根据数据包头部长度字段循环读取相应长度的内容; - 将应用层交给
TCP
的每个数据包的首、尾分别添加开始符、结束符。
HTTP(应用层)
HTTP
协议是Hyper Text Transfer Protocol(超文本传输协议)
的缩写,是用于从万维网(WWW:World Wide Web )
服务器传输超文本
到本地浏览器
的传送协议。HTTP
是一个基于TCP/IP
通信协议来传递数据(HTML,图片等文件,以及查询结果等)。
主要特点如下:
-
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有
GET、HEAD、POST
。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。 -
灵活:
HTTP
允许传输任意类型的数据对象。正在传输的类型由Content-Type
加以标记。 -
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
-
无状态:
HTTP
协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。 -
支持
B/S
及C/S
模式
HTTP 协议由哪几部分组成?
-
请求协议信息由 4 部分组成:请求行、请求头、空行、请求体
-
响应协议信息也由 4 部分组成:状态行、响应头、空行、响应体
使用
curl
命令查看协议详情:
HTTP状态码?
HTTP
状态码由三个十进制数字组成,第一个数字定义了状态码的类型。HTTP 状态码共有 5 种类型:1xx, 2xx, 3xx, 4xx, 5xx。类型解释以及部分常见状态码如下:
-
1XX (Informational)
: 接收的请求正在处理100 Continue
:表明请求到目前为止都处理的很正常,客户端可以继续发送请求或者忽略这个响应。 -
2XX (Success)
: 请求正常处理完毕200 OK
: 表示成功处理了请求。 -
3XX (Redirection)
: 需要进行附加操作以完成请求301 Moved Permanently
:永久性重定向。302 Found
:临时性重定向。 -
4XX (Client Error)
: 服务器无法处理请求403 Forbidden
:请求被服务器拒绝。404 Not Found
: 服务器找不到请求的网页。 -
5XX (Server Error)
: 服务器处理请求出错500 Internal Server Error
:服务器正在执行请求时发生错误。
状态码 301 和 302 的区别?
301
和302
状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL
地址,这个地址可以从响应头部字段Location
中获取(用户看到的效果就是他输入的地址A
瞬间变成了另一个地址B
)
301: 表示永久重定向。该状态码表示请求的资源已被分配了新的 URI
,以后应使用资源现在所指的 URI
。也就是说,如果已经把资源对应的 URI保存为书签了,这时应该按 Location
字段提示的 URI
重新保存。
302: 表示临时重定向。该状态码表示请求的资源已被分配了新的 URI
,希望用户(本次)能使用新的 URI
访问。和 301
状态码相似,但 302
状态码代表的资源不是被永久移动,只是临时性质的。换句话说,已移动的资源对应的URI 将来还有可能发生改变。比如,用户把 URI 保存成书签,但不会像 301
状态码出现时那样去更新书签,而是仍旧保留返回 302
状态码的页面对应的 URI
。
Forward和Redirect的区别?
Forward:客户端发出的请求被服务器内部进行转发,浏览器地址栏依然是之前的URL
。就如 SpringMVC
中,所有的请求都由 DispatcherServlet
处理后再在服务器内部进行派发。
Redirect:实际是两次HTTP
请求,服务器端在响应第一次请求的时候,让浏览器再向另外一个URL
发出请求,从而达到转发的目的。
HTTP 请求方法了解哪些?
HTTP/1.0
定义了三种请求方法:GET
, POST
和 HEAD
方法。
方法 | 描述 |
---|---|
GET | 最常用的方法之一,用于请求服务器响应某个资源,不应当对系统资源进行改变。 |
POST | 最常用的方法之一,用于将数据(表单等)提交至服务器以创建新的资源。 |
HEAD | HEAD 方法与 GET 方法的行为很类似,但服务器在响应中只返回首部,这就允许客户端在未获取实际资源的情况下,根据首部信息对资源进行检查。 |
HTTP/1.1
新增了:PUT
、PATCH
、DELETE
、CONNECT
、OPTIONS
、TRACE
共5种HTTP
请求方法。
方法 | 描述 |
---|---|
PUT | 用于将数据提交至服务器以更新之前存在的资源。 |
PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新;当资源不存在时,PATCH会创建一个新的资源。 |
DELETE | 请求服务器删除指定的资源。 |
CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
OPTIONS | 请求服务器告知其支持的各种功能。 |
TRACE | 请求服务器回显其收到的请求,主要用于测试或诊断。 |
备注:HTTP
规范定义了以上方法的行为,但实际开发中可以不遵守。例如:在GET
请求对应的接口中去更新资源,将会给自己带来麻烦。
HTTP幂等性了解吗?
在编程领域,对于同一个系统,在同样条件下,一次请求和重复多次请求对服端资源的影响是一致的,就称该操作为幂等的。
HTTP常见幂等方法:GET
、PUT
、DELETE
、
HTTP常见非幂等方法:POST
、PATCH
解释:
PUT:第一次和第N次请求对服务端资源的影响是相同的,所以是幂等的。例如将id
为1234
的账户金额改为1000
,多次调用对系统资源产生的影响是一致的。
DELETE:第一次和第N次请求对服务端资源的影响是相同的,所以是幂等的。假如存在一个删除 id
为 1234
的账户的接口,第一次请求时会删除,而后面所有请求的时候由于系统中已经没有该资源了,所以第一次和后面的请求对服务端资源的影响( id
为 1234
的资源不再存在)是相同的。
PATCH: URI
对应的资源不存在时服务端可以创建一个新资源,因此两次请求对服务端资源的影响可能会不同。并且服务端可以根据请求参数,动态的计算出某个值,例如每次请求后资源的某个参数减1,所以多次调用,资源会有不同的变化。综上,PATCH
方法是非幂等的。
更多:聊聊开发中幂等性问题
了解REST风格吗?
REST
是一种架构风格,即Representational State Transfer
的缩写,译为”表现层状态转化“。REST
的原则不仅仅适用于HTTP
协议,但由于REST
的应用场景绝大部分是WEB
应用,故以下讨论都基于HTTP
。
资源是网络上的一个实体,或者说是网络上的一个具体信息,一个资源可以被URI唯一标识。因此,表现层可以理解为资源的一种具体表现,如:文本文件、html文件等等。状态转化指客户端和服务端的交互过程中通过HTTP
协议提供的4个动作(GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。)对服务器资源进行操作,从而实现”表现层状态转化“。
备注:而RESTful API
就是符合REST
风格的API
GET 和 POST 的区别?
- 从功能上讲,
GET
一般用来从服务器上获取资源,POST
一般用来在服务器上新增资源; - 从
REST
服务角度上说,GET
是幂等的,而POST
不是幂等的; - 从请求参数形式上看,
GET
请求的数据会附在URL
之后,POST
请求会把提交的数据放置在是HTTP
请求报文的请求体中; - 就安全性而言,
POST
的安全性要比GET
的安全性高,因为 GET 请求提交的数据将明文出现在URL
上,而且POST
请求参数则被包装到请求体中,相对更安全; - 从请求的大小看,
GET
请求的长度受限于浏览器或服务器对URL
长度的限制,允许发送的数据量比较小,而POST
请求理论上是没有大小限制。
怎么知道 HTTP 的报文长度?
当传输的是静态文件时,服务端能够很清楚的知道将要响应内容的大小,可以通过响应头中的Content-Length
域来告诉客户端报文的长度。如果服务端预先不知道将要响应内容的大小(动态生成的页面)就需要在响应头中指明 Transfer-Encoding: chunked
。表示响应体是使用chunked
分块方式拼接成的,不需要Content-Length
指明长度。每一个分块包含十六进制的长度值和数据,最后一个分块长度值为0,表示实体结束,客户端可以以此为标志确认数据已经接收完毕。(这些是HTTP1.1
的内容,Content-Length
字段不是必需的,因为浏览器发现服务器关闭了TCP
连接,就表明收到的数据包已经全了)。
Keep-Alive(长连接) 和 非 Keep-Alive 区别?
可以通过请求头或响应头中的Connection
域查看是否是Keep-Alive
。
短连接:在HTTP/1.0
中默认使用短连接(也支持长连接,得手动设置Connection: keep-alive
)。客户端每个HTTP
请求和响应都会开启和关闭一个单独的TCP
连接。
长连接: 而从HTTP/1.1
起,默认使用长连接。同一个客户端和服务端之间的连续的多个HTTP
请求和响应可以通过一个TCP
连接来完成。但是一个长连接也不是一直保持,客户端在最后一个请求时,发送Connection: close
,明确要求服务器关闭TCP连接,也可以通过 keep-alive timeout
参数来设置。
HTTP1.0、HTTP1.1、HTTP2的主要变化?
HTTP1.1变化:
长连接:HTTP1.0
默认是短连接,HTTP1.1
默认支持长连接,且引入了流水线技术(pipelining
)。不仅多个请求可以复用同一个TCP
连接,并且同一个TCP
连接里面,客户端可以同时发送多个请求。这样就进一步改进了HTTP协议的效率。(流水线方式会存在”队头阻塞“:如果第一个请求被阻塞,即使后到的请求已经处理完毕,响应时依然要按请求的顺序依次响应)。
宽带和网络连接优化:HTTP1.0
会存在一些性能浪费,每次请求都返回整个对象,即使只需要对象的一部分。HTTP1.1
则可以通过设置range
头域,仅请求返回资源的某一部分,也就是返回码为206(Partial Content)
的时候,这对于性能优化很有必要。
引入Host头域:HTTP1.1
添加了Host
头域,请求头如果没指定Host
,则返回404
。在HTTP1.0
中认为每个IP
地址都只属于一台服务器,因此,请求消息中的URL
并没有传递主机名。但随着虚拟主机技术的发展,在一台物理主机上可以存在多个虚拟主机,并且它们共享一个IP
地址,仅靠IP
地址无法区分请求的是哪个虚拟主机,故HTTP1.1
加上了Host
头域来区分。
更多:HTTP中的Host字段
HTTP2 的变化:
二进制:HTTP1.X
(头信息肯定是文本(ASCII
编码),数据体可以是文本,也可以是二进制)的协议解析是基于文本格式,而HTTP2
(头信息和数据体都是二进制,并且统称为”帧”(frame
):头信息帧和数据帧)的协议解析是二进制格式,解析更加高效。
多路复用(Mutiplexing) : 可以复用TCP
连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”
header压缩: HTTP1.X
协议不带有状态,每次请求都必须附上所有信息。所以,请求的很多字段都是重复的,比如Cookie
和User Agent
,一模一样的内容,每次请求都必须附带,这会浪费很多带宽,也影响速度。HTTP2
对这一点做了优化,引入了头信息压缩机制(header compression
)。一方面,头信息使用gzip
或compress
压缩后再发送;另一方面,客户端和服务器同时维护一张“首部表”来跟踪和存储之前发送的头域(键-值对),对于不变的域,不再通过每次请求和响应发送;通信期间几乎不会改变的通用域键(User Agent、Accept
等等) 只需发送一次。
服务端推送(server push): 允许服务器未经请求,主动向客户端发送资源,这叫做服务器推送。常见场景是客户端请求一个网页,这个网页里面包含很多静态资源。正常情况下,客户端必须收到网页后,解析HTML源码,发现有静态资源,再发出静态资源请求。其实,服务器可以预期到客户端请求网页后,很可能会再请求静态资源,所以就主动把这些静态资源随着网页一起发给客户端了。
更多:一篇文章读懂 HTTP1.0 HTTP1.1 HTTP2.0 HTTPS
HTTP 和 HTTPS 的主要区别?
端口:HTTP协议端口为80
,HTTPS协议端口为443
;
安全性:HTTP
信息是明文传输;而HTTPS
协议的信息是经过SSL/TLS
协议加密后传输的。( TLS
(Transport Layer Security
,传输层安全协议) 是 SSL
(Secure Socket Layer
,安全套接字层)的升级版)。
数字证书:HTTPS
协议需要到 CA (Certificate Authority)
机构申请数字证书,绝大多数需要花钱申请。
响应速度和资源消耗:HTTPS
相比 HTTP
在 TCP
之上多了 SSL/TLS
协议,因此响应速度会更慢,资源消耗会更多。
HTTPS 的工作过程?
前置:SSL/TLS中使用了非对称加密,对称加密以及HASH算法。
对称加密:加解密秘钥一样,优点是加解密速度快,适合对大量数据加密;缺点是使用前需要传输给另一个使用方,容易泄露。
非对称加密:分为私钥和公钥,私钥自己保存无需发送,公钥则是公开的,公钥加密的信息只有私钥能解密(反之亦然)。非对称加密加解密速度慢,只适合少量数据加密。
完整性校验算法(hash算法):同一数据计算结果相同,一旦数据被修改结果就会改变。通常用来检查数据是否被篡改。
个HTTPS
请求实际上包含了两次HTTP
传输,可以细分为 4 步:
- 客户端向服务器发起
HTTPS
请求,连接到服务器的443
端口。 - 服务器将自己向
CA
申请的数字证书发送给客户端。数字证书包含了公钥、签名等信息。 - 客户端解析证书并对其进行验证。如果证书不是可信机构颁布,或者证书中的域名与实际域名不一 致,或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。 如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥。然后客户端还会生成一个随机码
KEY
,并使用公钥将其加密。随后客户端把加密后的随机码KEY
发送给服务器,作为后面对称加密的密钥。 - 服务器在收到消息后使用私钥解密得到随机码
KEY
,到此客户端和服务器就已经成功建立了安全连接。接下来就可以用对称加密进行通信了。
Cookie是什么?
HTTP Cookie
(也叫 Web Cookie
或浏览器 Cookie
)是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。通常可以用于个性化设置,浏览器行为跟踪。
Session是什么?
由于HTTP
协议是无状态的协议,所以服务器需要记录用户状态时就需要借助Session
机制。目前Session
常见实现要借助Cookie
,即服务器端创建一个Session
对象,同时会创建一个特殊的Cookie
对象(name
为”JSESSIONID
“,value
为Session
对象的ID
),然后将该Cookie
对象发送至浏览器。当浏览器端发送第N(N>1)
次请求到同一服务器时就会携带该name
为JSESSIONID
的Cookie
对象。服务器根据name
为JSESSIONID
的Cookie
的value(sessionId)
去查询对应Session
对象,从而区分不同用户。(Session
对象默认存活30
分钟)
Cookie和Session的区别?
- 作用范围不同,
Cookie
保存在客户端(浏览器),Session
保存在服务器端。 - 存取方式的不同,
Cookie
只能保存ASCII
编码的字符,Session
可以存任意数据类型,一般情况下我们可以在Session
中保持一些常用变量信息,比如说商品ID
,商品数量
(购物车场景)等。 - 有效期不同,
Cookie
可设置为长时间保持,比如我们经常使用的默认登录功能,Session
一般失效时间较短,客户端关闭或者Session
超时都会失效(Session
对象默认存活30
分钟)。 - 隐私策略不同,
Cookie
存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码 存储在Cookie
中导致信息被窃取;Session
存储在服务端,安全性相对Cookie
要好一些。 - 存储大小不同, 单个
Cookie
保存的数据量<= 4KB
;对于Session
来说并没有上限,但出于对服务器端的性能考虑,Session
内不要存放过多的东西,并且应设置Session
删除机制。
在浏览器中输入 URL
地址到显示主页的过程?
- 首先根据
URL
进行域名解析,得到对应IP
地址。解析时,首先查看浏览器DNS缓存
是否命中,没有的话再查看操作系统DNS缓存
(hosts
文件)是否命中,如果再没有命中就会借助域名服务器进行解析。 - 位于应用层浏览器的封装好
HTTP
请求报文后交给应用层的TCP
协议。 TCP
协议根据IP地址向服务器的80
端口发起三次握手以建立TCP
连接,随后将HTTP
报文作为自己的数据部分封装到TCP
报文段中发送出去。- 服务器上的
TCP
协议收到TCP
报文段后进行拆包得到HTTP
请求报文,HTTP
请求报文随后被应用层的服务器程序读取、解析和处理后,按照之前类似步骤响应数据给浏览器。 - 浏览器得到
HTTP
响应报文后进行解析,渲染并显示给用户。
计算机分层模型
- OSI 七层模型:大而全,但是比较复杂、而且是先有了理论模型,没有实际应用。
- TCP/IP 四层模型:是由实际应用发展总结出来的,从实质上讲,
TCP/IP
只有最上面三层,最下面一 层没有什么具体内容,TCP/IP
参考模型没有真正描述这一层的实现。 - 五层模型:五层模型只出现在计算机网络教学过程中,这是对七层模型和四层模型的一个折中,既 简洁又能将概念阐述清楚。
三种模型以及对应层次关系如下:
OSI
七层网络体系结构各层的主要功能:
-
应用层:为应用程序提供交互服务。在互联网中的应用层协议很多,如域名系统
DNS
,支持万维网 应用的HTTP
协议,支持电子邮件的SMTP
协议等。 -
表示层:主要负责数据格式的转换,如加密解密、转换翻译、压缩解压缩等。
-
会话层:负责在网络中的两节点之间建立、维持和终止通信,如服务器验证用户登录便是由会话层 完成的。
-
运输层:有时也译为传输层,向主机进程提供通用的数据传输服务。该层主要有以下两种协议:
-
TCP
:提供面向连接的、可靠的数据传输服务; -
UDP
:提供无连接的、尽最大努力的数据传输服务,但不保证数据传输的可靠性。
-
-
网络层:选择合适的路由和交换结点,确保数据及时传送。主要包括
IP
协议。 -
数据链路层:数据链路层通常简称为链路层。将网络层传下来的
IP
数据包组装成帧,并再相邻节点 的链路上传送帧。 -
物理层 :实现相邻节点间比特流的透明传输,尽可能屏蔽传输介质和通信手段的差异。