网络层次划分
OSI七层网络模型
- 应用层:
Application Layer
重要协议:HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)、DNS(域名查询)、Telnet(远程登录)
作用:为应用软件而设的接口,定义的是应用进程间通讯和交互的规则
传递对象:报文 - (表达层):
Presentation Layer
作用:处理通信系统间交换信息,包括数据格式变化、数据加密与解密(base64)、数据压缩与解压
URL加密、图片解编码 - (会话层):
Session Layer
作用:负责在数据传输中设置和维护网络中两台计算机之间的通信连接,建立和管理会话
服务器验证用户登录,断点续传 - 传输层:
Transport Layer
重要协议:TCP、UDP
作用:端到端传输数据,为两台主机中的进程提供通信服务,也能处理流量控制,差错校验、数据包次序等传输问题
传递对象:传输协议分组
设备:网关 - 网络层:
Network Layer
重要协议:IP、ARP(地址解析协议)、RARP(逆地址解析协议)、ICMP(因特网报文协议)
作用:IP寻址,负责为两台主机提供通信服务,并通过选择合适的路由将数据传递到目标主机,实现不同网络之间的路径选择,分组传输,路由器的选择与转发
传递对象:IP数据报文
设备:路由器、三层交换机,防火墙 - 数据链路层:
Data Link Layer
作用:链路控制+媒体访问,物理地址寻址(MAC)、数据的成帧(比特组合成字节,再将字节组合成帧)、如何传输、流量控制、数据的检错、重发 - 传递对象:帧
设备:网卡、网桥、以太网(二层)交换机 - 物理层:
Physics Layer
物理接口通信通道上的原始比特流的传输
传递对象:比特
设备:中继器、集线器、调制解调器、网线、双绞线、同轴电缆
TCP/IP五层网络模型中,ARP协议属于IP层;在OSI模型中,ARP协议属于链路层
DNS
DNS相关概念
DNS(DomainNameSystem
),域名系统用于命名组织到域层次结构中计算机和网络服务,将URL转换为IP地址
DNS解析过程
- 首先会查询 hosts 文件是否有对应的网址映射关系。如果有,优先采取
- 查找本地 DNS 解析器缓存, 如果有,取本地缓存
- 如果 hosts 与本地 DNS 解析器缓存都没有相应的网址映射关系,首先会找 TCP/IP 参数中设置的首选 DNS 服务器(本地 DNS 服务器),此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性
- 如果要查询的域名,不由本地 DNS 服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个 IP 地址映射,完成域名解析,此解析不具有权威性
- 如果上面都失败,则查看是否采用了转发模式,如果未用转发模式,往上一级域名,重复上面的动作,进行查询,直至找到 www.qq.com 主机
- 如果用的是转发模式,此 DNS 服务器就会把请求转发至上一级 DNS 服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根 DNS 或把转请求转至上上级,以此循环。不管是本地 DNS 服务器用是是转发,还是根提示,最后都是把结果返回给本地 DNS 服务器,由此 DNS 服务器再返回给客户机
ARP
ARP相关概念
ARP(Address Resolution Protocol
):根据 IP 地址获取物理地址的一个 TCP/IP 协议。主机发送信息时将包含目标IP地址的 ARP 请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机 ARP 缓存中并保留一定时间,下次请求时直接查询 ARP 缓存以节约资源。当主机 A 要与主机 B 通信时,地址解析协议可以将主机 B 的 IP 地址(192.168.1.2)解析成主机B的MAC 地址(0A-11-22-33-44-02)
TCP/IP
TCP相关概念
TCP:Transmission Control Protocol
,传输控制协议
UDP:User Datagram Protocol
,用户数据报协议
TCP报文首部格式:
传输层-TCP 和 网络层-IP 分别解决了网络什么样的问题?
TCP负责建立连接,IP负责找到具体的机器
TCP建立/断开连接
TCP三次握手
首先 Client 端发送连接请求报文,Server 段接受连接后回复 ACK 报文,并为这次连接分配资源。Client 端接收到 ACK 报文后也向 Server 段发生 ACK 报文,并分配资源,这样 TCP 连接就建立完成
- 第一次握手:建立连接时,客户端发送 SYN(syn=j)包到服务器,进入SYN_SENT状态,等待服务器确认
- 第二次握手:服务器收到 SYN 包,确认客户的SYN(ack=j+1),自己也发送一个SYN(syn=k)包,
即 SYN+ACK 包,服务器进入SYN_RCVD状态 - 第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1),客户端和服务器进入 ESTAB_LISHED 状态
seq:"sequance"序列号
ack:"acknowledge"确认号
SYN:"synchronize"请求同步标志
ACK:"acknowledge"确认标志"
FIN:"Final"结束标志
为什么需要三次握手才能建立连接,两次不行吗?
确认 Server 和 Client 的发送及接收能力正常,指定自己的初始化序列号为后面的可靠性传输做准备
- 相互确认:两次握手只能保证单向连接畅通
- 防止重复连接:为了防止已失效的请求报文段突然又传送到了服务端而产生连接的误判
在网络状况比较复杂或网络状况比较差的情况下(丢包),发送方可能会连续发送多次建立连接的请求
如果 TCP 握手的次数只有两次,这个被客户端认为失效的消息到达了 Server,对 Server 而言,以
为这是一个新的请求连接消息,就向 Client 发送确认并建立连接。对客户而言,它认为没有给 Server 再次发送连接请求(因为上次的通话已经结束)所以客户忽略 Server 的这个确认从而不发送数据,但 Server 则会一直等待客户的消息而处于忙等状态。这就导致了服务器资源被浪费
SYN超时
Server 收到 Client 发送的SYN,回复SYN+ACK时,Client 由于某种原因掉线,未收到ACK确认。Server 不断重试直至超时(Linux默认等待63s断开连接)
建立连接后,客户端出现故障
保活机制:
- Server 向 Client 发送保活探测报文,如果未收到响应则继续发送
- 尝试次数达到保活探测数仍未收到响应则中断连接
TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2h,若 2h 还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75s 发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接
TCP四次挥手
Client 端发起中断连接请求,也就是发送 FIN 报文。Server 端接到 FIN 报文后,意思是说"Client 端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭 Socket,可以继续发送数据。所以你先发送 ACK,"告诉 Client 端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候 Client 端就进入 FIN_WAIT 状态,继续等待 Server 端的 FIN 报文。当 Server 端确定数据已发送完成,则向 Client端发送 FIN 报文,"告诉 Client 端,好了,我这边数据发完了,准备好关闭连接了"。Client 端收到 FIN 报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕 Server 端不知道要关闭,所以发送 ACK 后进入TIME_WAIT 状态,如果 Server 端没有收到 ACK 则可以重传。",Server 端收到 ACK 后,"就知道可以断开连接了"。Client 端等待了 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那 Client 端也可以关闭连接了,TCP连接就这样关闭
- 第一次挥手:Client 发送一个 FIN,关闭 Client 到 Server 的数据传送,Client 进入 FIN_WAIT_1状态
- 第二次挥手:Server 收到 FIN 后,发送一个 ACK 给 Client,确定序号为收到序号 +1(与 SYN 相同,一个 FIN 占用一个序号),Server 进入 CLOSE_WAIT 状态
- 第三次挥手:Server 发送一个 FIN,用来关闭 Server 到 Client 数据传送,Server 进入 LAST_ACK 状态
- 第四次挥手:Client 收到 FIN 后,Client 进入 TIME_WAIT 状态,接着发送一个 ACK 给 Server,确定序号为收到序号+1, Server 进入 CLOSE 状态,完成四次挥手
为什么挥手比建立连接多一次?
连接建立过程中(握手),服务器端接收到建立连接的请求并回复 ACK 后,此时没有数据传输。所以在建立连接时第2/3步可合并。客户端发送完数据后请求断开连接(挥手),服务端可能还有数据需要发送,若同时回 ACK 和 FIN 报文段给客户端,可能造成数据的损坏或错误。所以服务器先发送 ACK 报文段,等服务端数据发送完再发送FIN、ACK 报文段,就可以保证传输数据的完整性
为什么需要四次挥手才能断开连接
TCP 是全双工、点对点通信,发送方和接收方都需要 FIN 报文和 ACK 报文。假如现在你是客户端你想断开跟Server 的所有连接该怎么做?第一步,你自己先停止向 Server 端发送数据,并等待 Server 的回复。但事情还没有完,虽然你自身不往 Server 发送数据了,但是因为你们之前已经建立好平等的连接了,所以此时他也有主动权向你发送数据;故 Server 端还得终止主动向你发送数据,并等待你的确认
为什么要四次挥手?为什么不是两次?为什么不是三次?
关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方是否现在关闭发送数据通道,需要上层应用来决定,因此,己方 ACK 和 FIN 一般都会分开发送
为什么不是两次?
- 两次情况客户端说完结束就立马断开不再接收,无法确认服务端是否接收到断开消息,但且服务端可能还有消息未发送完
为什么不是三次?
- 3 次情况服务端接收到断开消息,向客户端发送确认接受消息,客户端未给最后确认断开的回复
为什么客户端在第四次挥手后还会等待2MSL?
MSL(Maximum Segment Lifetime 最长报文段寿命)报文在网络上存在的最长时间,超过这个时间报文将被丢弃,保证第四次握手客户端发送的最后一个ACK报文段能够到达服务端。由于网络故障等原因,很可能发生 ACK 报文丢失。如果服务端没接收到 ACK 报文的话,会重新发送 FIN 报文,只有当客户端等待了 2MSL 都没有收到重发的 FIN 报文时就表示服务端是正常收到了 ACK 报文,那么这个时候客户端就可以关闭了。防止“已失效的连接请求报文段”出现在本连接中。客户端在发送完最后一个 ACK 报文段后,再经过 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧连接请求报文段
四次挥手的状态,TIME_WAIT过多要怎么解决?
在高并发短连接的 TCP 服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量Socket 处于 TIME_WAIT 状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上
解决:打开系统的 TIME_WAIT 重用和快速回收
- 编辑内核文件 /etc/sysctl.conf
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭; net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭; net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。 net.ipv4.tcp_fin_timeout 修改系默认的 TIMEOUT 时间 net.ipv4.tcp_keepalive_time = 1200 # 表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。 net.ipv4.ip_local_port_range = 1024 65000 # 表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。 net.ipv4.tcp_max_syn_backlog = 8192 # 表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。 net.ipv4.tcp_max_tw_buckets = 5000 # 表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。 默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死
- 然后执行 /sbin/sysctl -p 让参数生效
高并发:可以让服务器在短时间范围内同时占用大量端口
短连接:业务处理+传输数据的时间 远远小于 TIME_WAIT超时的时间”的连接
TCP可靠传输
TCP如何保证可靠传输
- 校验和:在数据传输的过程中,将发送的数据段都当做一个 16 位的整数。将这些整数加起来。并且前面的进位不能丢弃,补在后面,最后取反,得到校验和。发送方:在发送数据之前计算检验和,并进行校验和的填充;接收方:收到数据后,对数据以同样的方式进行计算,求出校验和,与发送方的进行比对
- 序列号与确认应答:TCP 传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送 ACK 报文。这个 ACK 报文当中带有对应的确认序列号(TCP 传输时将每个字节的数据都进行了编号),告诉发送方,接收到了哪些数据,下一次的数据从哪里发
- 超时重传:发送方在发送完数据后等待一个时间,时间到达没有接收到 ACK 报文,那么对刚才发送的数据进行重新发送。如果数据在传输过程中由于网络原因等直接全体丢包,接收方根本没有接收到,超时重传后接收方收到二次重发的数据后,便进行 ACK 应答;如果接收方接收到了响应的数据,但是发送的 ACK 报文响应却由于网络原因丢包了,超时重传后接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送 ACK 应答
- 连接管理:三次握手与四次挥手的过程
- 流量控制:接收端在接收到数据后,对其进行处理。如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了。此时如果发送端仍旧发送数据,那么接下来发送的数据都会丢包,继而导致丢包的一系列连锁反应,超时重传呀什么的。而TCP根据接收端对数据的处理能力,决定发送端的发送速度。在 TCP 协议的报头信息当中,有一个 16 位字段的窗口大小。窗口大小的内容实际上是接收端接收数据缓冲区的剩余大小。这个数字越大,证明接收端接收缓冲区的剩余空间越大,网络的吞吐量越大。接收端会在确认应答发送 ACK 报文时,将自己的即时窗口大小填入,并跟随 ACK 报文一起发送过去。而发送方根据ACK报文里的窗口大小的值的改变进而改变自己的发送速度。如果接收到窗口大小的值为 0,那么发送方将停止发送数据。并定期的向接收端发送窗口探测数据段,让接收端把窗口大小告诉发送端
- 拥塞控制:TCP 传输的过程中,发送端开始发送数据的时候,如果刚开始就发送大量的数据,那么就可能造成一些问题。网络可能在开始的时候就很拥堵,如果给网络中在扔出大量数据,那么这个拥堵就会加剧。拥堵的加剧就会产生大量的丢包,就对大量的超时重传,严重影响传输。TCP 引入了慢启动的机制,在开始发送数据时,先发送少量的数据探路。探清当前的网络状态如何,再决定多大的速度进行传输。这时候就引入一个叫做拥塞窗口的概念。发送刚开始定义拥塞窗口为 1,每次收到ACK应答,拥塞窗口加 1。在发送数据之前,首先将拥塞窗口与接收端反馈的窗口大小比对,取较小的值作为实际发送的窗口
UDP 如何保证可靠的传输
最简单的方式是在应用层模仿传输层 TCP 的可靠性传输。下面不考虑拥塞处理,可靠 UDP 的简单设计。
- 添加 seq/ack 机制,确保数据发送到对端
- 添加发送和接收缓冲区,主要是用户超时重传
- 添加超时重传机制
详细说明:
- 发送端发送数据时,生成一个随机 seq=x,然后每一片按照数据大小分配 seq。
- 数据到达接收端后接收端放入缓存,并发送一个 ack=x 的包,表示对方已经收到了数据。
- 发送端收到了 ack 包后,删除缓冲区对应的数据。
- 时间到后,发送端定时任务检查是否需要重传数据
TCP 流量控制与拥塞控制
- 流量控制
所谓流量控制就是让发送方的发送速率不要太快,让接收方来得及接收。如果接收方来不及接收发送方发送的数据,那么就会有分组丢失。在 TCP 中利用可变长的滑动窗口机制可以很方便的在 TCP 连接上实现对发送方的流量控制。主要的方式是接收方返回的 ACK 中会包含自己的接收窗口大小,以控制发送方此次发送的数据量大小(发送窗口大小) - 拥塞控制
在实际的网络通信系统中,除了发送方和接收方外,还有路由器,交换机等复杂的网络传输线路,此时就需要拥塞控制。拥塞控制是作用于网络的,它是防止过多的数据注入到网络中,避免出现网络负载过大的情况。常用的解决方法有:慢开始和拥塞避免、快重传和快恢复
拥塞控制和流量控制区别
拥塞控制往往是一种全局的,防止过多的数据注入到网络之中,而 TCP 连接的端点只要不能收到对方的确认信息,猜想在网络中发生了拥塞,但并不知道发生在何处,因此,流量控制往往指点对点通信量的控制,是端到端的问题
TCP的拥塞控制,具体过程是怎么样的?
拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能承受现有的网络负荷。
流量控制往往指的是点对点通信量的控制,是个端到端的问题。流量控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接受。
拥塞控制的四种算法:
- 慢开始(Slow-start):先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理
- 拥塞避免(Congestion Avoidance):让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多
- 快重传(Fast Restrangsmit):首先要求接收方每收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时才进行捎带确认。(如果当发送端接收到三个重复的确认ACK时,则断定分组丢失,立即重传丢失的报文段,而不必等待重传计时器超时)
- 快回复(Fast Recovery):当发送方连续收到三个重复确认,就执行“乘法减小”算法,把慢开始门限ssthresh减半。这是为了预防网络发生拥塞。请注意:接下去不执行慢开始算法。由于发送方现在认为网络很可能没有发生拥塞,因此与慢开始不同之处是现在不执行慢开始算法(即拥塞窗口cwnd现在不设置为1),而是把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大
TCP 粘包及处理
粘包是指为了防止数据量过小导致大量传输,全将多个 TCP 段合并成一个发送。就是将若干个包数据粘成一个包,从接收缓冲区看,后一包数据的头紧接送前一包数据的尾。因为 TCP 层传输是流式传输,流,最大的问题是没有边界,没有边界就会造成数据粘在一起
拆包就是将任务拆分处理了,降低出错率
造成粘包的场景
- 接收方不及时接收缓冲区的包,造成多个包接收
- 因为 TCP 默认使用 Nagle 算法,这个算法本身也可能会导致粘包问题
- 由于 TCP 的复用造成粘包。由于 TCP 连接的复用性,建立一条连接可以供一台主机上的多个进程使用,那么多种不同结构的数据到 TCP 的流式传输里,边界分割肯定会出现奇葩的问题
- 数据包过大造成的粘包问题,比如应用进程缓冲区的一条消息内容大小超过了发送缓存区的大小,就可能产生粘包,因为消息已经被分割了,前一部分已经被接收了,但另一部分可能刚放入缓存冲区准备发送,这样就会导致后一部分粘包
- 流量控制,拥塞控制也可能导致粘包
粘包怎么处理
- 如果是 Nagle 算法导致的,结合应用场景适当关闭算法就可以了
- 如果不是
- 尾部标记序列。通过特殊标识符表示数据包的边界,比如\n\r\t 或一些隐藏字符
- 头部标记分步接收。在 TCP 报文的头部加上表示数据长度。使用带消息头的协议,消息头存储开始标识及消息长度信息,服务商获取消息头的时候解析出消息长度,然后向后读取该长度的内容
- 应用层发送数据时定长发送,服务端读取既定长度的内容作为一条完整消息,如果不够长,就在空位上补固定字符
UDP 为什么不会粘包
- 因为 UDP 是面向消息的协议,UDP 段都是一条消息,应用程序必须以消息为单位提取数据,不能一次提取任意字节的数据
- UDP 具有保护消息边界,在每个 UDP 包中有消息头(消息来源地址,端口信息等),这样对于接收端来说容易进行分区处理。传输协议把数据当作一条独立的消息在网上传输,接收方只能接收独立的消息,如果消息内容过大,超过接收方一次所能接受的大小,就会丢失一部分数据,因为就算是丢失,它也不会分两次去接收
TCP 协议丢包后,如何解决丢包的问题
为了满足 TCP 协议不丢包。TCP 协议有如下规定:
- 数据分片:发送端对数据进行分片,接受端要对数据进行重组,由 TCP 确定分片的大小并控制分片和重组
- 到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认
- 超时重发:发送方在发送分片时设置超时定时器,在定时器超时之后没有收到相应的确认,重发分片数据
- 滑动窗口:TCP 连接的每一方的接受缓冲空间大小固定,接收端只允许另一端发送接收端缓冲区所能接纳的数据,TCP 在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出
- 失序处理:作为 IP 数据报来传输的 TCP 分片到达时可能会失序,TCP 将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层
- 重复处理:作为 IP 数据报来传输的 TCP 分片会发生重复,TCP 的接收端必须丢弃重复的数据
- 数据校验:TCP 将保持它首部和数据的检验和,这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到分片的检验或有差错,TCP 将丢弃这个分片,并不确认收到此报文段导致对端超时并重发
TCP/UDP
TCP/UDP区别
TCP | UDP | |
---|---|---|
是否连接 | 面向连接 | 面向非连接 |
是否可靠 | 可靠传输(流量控制和拥塞控制) | 不可靠(尽最大努力交付) |
传输方式 | 面向字节流 | 面向报文 |
连接对象 | 一对一通信 | 一对一、一对多、多对一、多对多 |
首部开销 | 重量级(数据包20字节) | 轻量级(数据包8字节) |
适用场景 | 要求可靠传输的应用(文件传输) | 实时应用(IP电话、视频会议、直播) |
TCP、UDP可否同时监听同一端口
同一台机器的同一个端口只可以被一个进程使用,一个进程使用同一个端口同时监听 TCP、UDP 请求是可以
端口的唯一性的标识不是端口号,而是端口号和协议名称的组合
TCP如何保证传输可靠
- 数据分片:发送端对数据进行分片,接受端要对数据进行重组,由TCP确定分片的大小并控制分片和重组
- 到达确认:接收端接收到分片数据时,根据分片数据序号向发送端发送一个确认
- 超时重发:发送方在发送分片时设置超时定时器,在定时器超时之后没有收到相应的确认,重发分片数据
- 滑动窗口:TCP 连接每一方接受缓冲空间大小固定,接收端只允许另一端发送接收端缓冲区所能接纳数据
TCP 在滑动窗口的基础上提供流量控制,防止较快主机致使较慢主机的缓冲区溢出 - 失序处理:作为 IP 数据报来传输 TCP 分片到达时可能失序,TCP 将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层
- 重复处理:作为 IP 数据报来传输的 TCP 分片会发生重复,TCP 的接收端必须丢弃重复的数据;
- 数据校验:TCP 将保持首部和数据的检验和(端到端),目的是检测数据在传输过程中的任何变化。如果收到分片的检验或有差错,TCP 将丢弃这个分片,并不确认收到此报文段导致对端超时并重发
TCP/UDP应用场景
TCP支持的应用协议:HTTP(万维网)、Telnet(远程登录)、FTP(文件传输协议)、SMTP(简单邮件传输协议)
UDP支持的应用协议:NFS(网络文件系统)、DNS(主域名称系统)、TFTP(通用文件传输协议)
IP
IP是怎么寻址
HTTP/HTTPS
HTTP
HTTP协议简介
HTTP是什么
HTTP 全称为 Hyper Text Transfer Protocol,被译为超文本传输协议,用于从万维网服务器传输超文本到本地浏览器的传送协议。协议就是双方约定好的格式,确保双方都能理解这种格式。
- HTTP 协议(HyperText Transfer Protocol,超文本传输协议)因特网上应用最为广泛的网络传输协议
- HTTP 是基于 TCP/IP 通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)
- HTTP 是一个应用层协议,由请求和响应构成,标准的客户端服务器模型
HTTP特点
- HTTP允许传输任意类型的数据:传输的类型由 Content-Type 加以标记
- HTTP 是一个无状态的协议:对于客户端每次发送的请求,服务器都认为是一个新的请求,上一次会话和下一次会话之间没有联系
- 支持客户端/服务器模式
HTTP发展史
- HTTP/0.9
只有一个命令GET
没有HEADER等描述数据的信息
服务器发送完毕,就关闭TCP连接 - HTTP/1.0
增加了很多命令
增加status code和header
多字符集支持、多部分发送、权限、缓存等 - HTTP/1.1
持久连接
pipeline
增加host和其他一些命令 - HTTP 2
所有数据以二进制传输(多路复用)
同一个连接里面发送多个请求不再需要按照顺序来
头信息压缩以及推送等提高效率的功能
URI、URL:
- URI,Uniform Resource Identifier/统一资源标志符
- URL,Uniform Resource Locator/统一资源定位器
URL解析:
http://localhost:8080/admin-index/article
- HTTP Protocol:http、https
- Host Name:localhost
- Port:8080
- Path:admin-index/article
HTTP 1.0和1.1的区别
HTTP 2.0和1.1的区别
- 新的二进制格式:
HTTP 1.1基于文本格式传输数据
HTTP 2.0采用二进制格式传输数据,解析更高效 - 多路复用:
在一个连接里,HTTP 2.0允许同时发送多个请求或响应,并且这些请求或响应能够并行的传输而不被阻塞 - 头部压缩:
HTTP1.1的header带有大量信息,而且每次都要重复发送
HTTP2.0把header从数据中分离,并封装成头帧和数据帧,使用特定算法压缩头帧,有效减少头信息大小。并且HTTP2.0在客户端和服务器端记录了之前发送的键值对,对于相同的数据,不会重复发送。比如请求a发送了所有的头信息字段,请求b则只需要发送差异数据,这样可以减少冗余数据,降低开销。 - 服务端推送:
HTTP 2.0允许服务器向客户端推送资源,无需客户端发送请求到服务器获取
HTTP报文格式
HTTP报文:用于 HTTP 协议交互的信息
请求消息Request
- 请求行(request line):请求方法、协议版本
- 请求头部(header):请求 URI、客户端信息
- 空行
- 请求数据:用户信息和资源信息
GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi
HTTP报文的请求头部
- Accept:浏览器可接受的MIME类型
Accept-Charset:浏览器可接受的字符集
Accept-Encoding:浏览器能够进行解码的数据编码方式
Accept-Language:浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到
Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中 - Connection:表示是否需要持久连接。浏览器与服务器之间连接的类型。如果Servlet看到这里的值为Keep-Alive,或者看到请求使用的是HTTP 1.1(默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length 头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小 Content-Length:表示请求消息正文的长度
- Cookie:设置Cookie,这是最重要的请求头信息之一
- Host:初始URL中的主机和端口
- Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝
- Referer:发出请求的页面的 URL
- User-Agent:浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用
响应消息Response
- 状态行:协议版本、状态码
- 响应头部:服务器名称、资源标识
- 内容实体:服务端返回的资源信息
# 状态行
HTTP/1.1 200 OK
# 消息报头
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/xml, application/x-www-form-urlencoded, multipart/form-data, application/json
# 空行
# 响应正文
<html> ... </html>
HTTP报文的响应头部
- Date:表示消息发送的时间,时间的描述格式由 rfc822 定义
- Server:服务器名称
- Connection:浏览器与服务器之间连接的类型
- Cache-Control:控制 HTTP 缓存
- content-type:表示后面的文档属于什么 MIME 类型
HTTP两个报文发送后接收是按顺序的吗?
HTTP状态码
- 1XX:指示信息,表示请求已接收,继续处理
100:Continue,表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应 - 2XX:成功,请求已被成功接收、理解、接收
200:OK,正常返回信息 - 3XX:重定向,要完成请求必须进行更进一步的操作
- 4XX:客户端错误,请求有语法错误或请求无法实现
400:bad request,客户端请求有语法错误,不能被服务器所理解
401:unauthorized,请求未经授权
403:forbidden,服务器收到请求,但拒绝提供服务
404:Not Found,请求资源不存在(输入错误的URL) - 5XX:服务器端错误,服务器未能实现合法的请求
500:Internal Server Error,服务期发生不可预期的错误
502:作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
503:Server unavailiable,临时的服务器维护或者过载,服务器当前无法处理请求
401和403的区别
- 401 Unauthorized:表示缺失或错误的认证。它是为了认证设计的,而不是为了授权设计的。收到401响应,表示请求没有被认证—压根没有认证或者认证不正确—但是请重新认证和重试。(一般在响应头部包含一个WWW-Authenticate来描述如何认证)。通常由Web服务器返回,而不是Web应用。从性质上来说是临时的东西。(服务器要求客户端重试)
- 403 Forbidden:关于授权方面的,当用户被认证后,但用户没有被授权在特定资源上执行操作。从性质上来说是永久的东西,和应用的业务逻辑相关联。它比401更具体,更实际。收到403响应表示服务器完成认证过程,但是客户端请求没有权限去访问要求的资源
301和302的区别
301和302都表示重定向,浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址
- 301 redirect: 永久性转移(Permanently Moved),旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址。场景:域名跳转
- 302 redirect: 暂时性转移(Temporarily Moved ):旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。场景:临时跳转,比如未登陆的用户访问用户中心重定向到登录页面;访问 404 页面会重新定向到首页
重定向 Redirect
重定向可实现许多目标:
- 站点维护或停机期间的临时重定向
- 永久重定向将在更改站点的URL,上传文件时的进度页等之后保留现有的链接/书签。
- 上传文件时的表示进度的页面
HTTP 协议的重定向响应的状态码为 3xx
HTTP长连接和短连接
HTTP 的长连接和短连接本质上是 TCP 长连接和短连接。HTTP 属于应用层协议,在传输层使用 TCP 协议,在网络层使用 IP 协议。 IP 协议主要解决网络路由和寻址问题,TCP 协议主要解决如何在 IP 层之上可靠地传递数据包,使得网络上接收端收到发送端所发出的所有包,并且顺序与发送顺序一致
HTTP 协议是无状态的,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。也就是说,打开一个服务器上的网页和上一次打开这个服务器上的网页之间没有任何联系。HTTP 是一个无状态的面向连接的协议,无状态不代表 HTTP 不能保持 TCP 连接,更不能代表 HTTP 使用的是 UDP 协议(无连接)
在 HTTP 1.0 中默认使用短连接:客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。当客户端浏览器访问的某个 HTML 或其他类型的 Web 页中包含有其他的 Web 资源(如 JavaScript 文件、图像文件、CSS文件等),每遇到这样一个 Web 资源,浏览器就会重新建立一个 HTTP 会话
从 HTTP 1.1 起,默认使用长连接,用以保持连接特性:当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。要使用长连接,客户端和服务器的 HTTP 首部的 Connection 都要设置为 keep-alive,才能支持长连接。keep-alive 不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间。实现长连接需要客户端和服务端都支持长连接。使用长连接的 HTTP 协议,会在响应头加入:Connection:keep-alive
HTTP 长连接指的是复用 TCP 连接。多个 HTTP 请求可以复用同一个 TCP 连接,这就节省了 TCP 连接建立和断开的消耗
一个TCP连接可以对应几个HTTP请求?
如果维持连接,一个 TCP 连接是可以发送多个HTTP请求
一个TCP连接中的HTTP请求发送可以一起发送吗(一起发三个请求,再三个响应一起接收)?
HTTP 1.1 存在一个问题,单个TCP连接在同一时刻只能处理一个请求
在HTTP 1.1 可以完成多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的
在HTTP 1.1 时代,浏览器是如何提高页面加载效率:
1.维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
2.和服务器建立多个 TCP 连接
浏览器对同一Host建立TCP连接的数量有没限制
Chrome 最多允许对同一个 Host 建立 6 个 TCP 连接。不同的浏览器有一些区别
HTTP的请求方法
对资源的增,删,改,查操作,其实都可以通过GET/POST完成,不需要用到PUT和DELETE
作用 | HTTP报文信息存放位置 | 幂等 | 说明 | 数据大小限制 | |
---|---|---|---|---|---|
Get | 查 | URL | 幂等 | 会被浏览器主动缓存;?分割URL和参数,参数之间以&相连(限制:整个URL长度) | 一般不超过2KB |
Post | 改 | 报文体 | 非幂等 | 不可缓存 | 理论上没有限制 |
Put | 增 | 非幂等 | 向指定资源位置上传其最新内容 | ||
Delete | 删 | 幂等 | 请求服务器删除 Request-URI 所标识的资源 |
补充:
- HEAD:head 方法用于获取报文首部,不返回报文主体
- OPTIONS:向服务器发送该方返回对指定资源所支持的 HTTP 请求方法
安全:该操作用于获取信息而非修改信息。仅是获取资源信息,像数据库查询,不修改数据,不影响资源状态
幂等:对同一URL的多个请求应该返回同样的结果
Get/Post区别
传送方式 | 传送长度 | 产生数据包 | 安全性 | 使用 | |
---|---|---|---|---|---|
Get | 地址栏传输 | 有长度限制 | 1个:HTTP Header 和 Data 一并发送,服务器响应 200 | 较弱 | 数据查询 |
Post | 报文传输 | 无长度限制 | 2个:先发送 HTTP Header,服务器响应 100-Continue,浏览器再发送 Data,服务器响应 200 | 较强 | 数据增删改 |
get 请求会被浏览器主动 cache,而 post 不会,除非手动设置
get 方法一般用于请求,比如你在浏览器地址栏输入 www.baidu.com 其实就是发送了一个 get 请求,它的主要特征是请求服务器返回资源,而 post 方法一般用于 <form>表单的提交,相当于是把信息提交给服务器,等待服务器作出响应,get 相当于一个是 pull/拉的操作,而 post 相当于是一个 push/推的操作
get 请求在发送过程中会产生一个 TCP 数据包;post 在发送过程中会产生两个 TCP 数据包。对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)
多次Post怎么保证数据安全
如果不小心提交了两次重复的数据,要怎么解决
操作:重复点击或者网络重发
- 点击提交按钮两次
- 使用浏览器后退按钮重复之前的操作,导致重复提交表单
- Nginx重发等情况
解决:
-
使用Post/Redirect/Get模式
Post-Redirect-Get (PRG)模式:在提交后执行页面重定向。能避免用户按F5导致的重复提交,而其也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退按导致的同样问题
-
在session中存放一个特殊标志
在服务器端,生成一个唯一的标识符,将它存入session,同时将它写入表单的隐藏字段中,然后将表单页面发给浏览器,用户录入信息后点击提交,在服务器端,获取表单中隐藏字段的值,与session中的唯一标识符比较,相等说明是首次提交,就处理本次请求,然后将session中的唯一标识符移除;不相等说明是重复提交,就不再处理
-
乐观锁
insert使用唯一索引 update使用 乐观锁 version版本法
HTTP无状态解决—Cookie/Session
HTTP是无状态协议,如何保存用户状态?
用户登录信息可以有哪些方式保存
HTTP不保存状态,即⽆状态(stateless)协议。HTTP 自身不对请求和响应之间的通信状态进行保存
- 基于Cookie 实现的会话保持:一小段文本信息。通过检查客户身上的“通行证”来确定客户身份的话。客户端请求服务器,如果服务器需要记录该用户状态,就使用 Response 向客户端浏览器发送一个 Cookie。客户端浏览器会把 Cookie 保存。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。减轻服务器存储压力。缺点:该方式不够安全,因为状态信息存储在客户端,这意味着不能在会话中保存机密数据。除此之外,浏览器每次发起 HTTP 请求时都需要发送额外的 Cookie 到服务器端,会占用更多带宽
- 基于 Session 实现的会话保持:记录客户状态的机制,通过检查服务器上的“客户明细表”来确认客户身份。不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。服务器把客户端信息以某种形式记录在服务器上。如果客户端请求 Cookie 里不包含有 SessionID,则为客户端创建一个 Session 并生成一个与此 Session 相关的 SessionID。客户端浏览器再次访问时,服务器按照这个SessionID 把 Session 从服务器内存中查出
Cookie/Session的工作原理
Cookie:
- 浏览器端第一次发送请求到服务器端
- 服务器端创建 Cookie,该 Cookie 中包含用户的信息,服务器会通过响应携带 Cookie,在产生响应时会产生 Set-Cookie 响应头,然后将该 Cookie 发送到浏览器端,max-age 和 expires 设置过期时间
- 当浏览器再次向服务器发送请求时,会产生 Cookie 请求头,将之前服务器的 Cookie 信息再发送给服务器,下次请求会自动带上
- 服务器端通过 Cookie 中携带的数据跟踪用户状态
Session:
- 浏览器端第一次发送请求到服务器端
- 服务器端创建一个 Session,同时会创建一个特殊的 Cookie(name 为 JSESSIONID 的固定值,value为session 对象的 id),然后将该 Cookie 发送至浏览器端
- 浏览器端再次访问服务器端时就会携带该name为JSESSIONID的Cookie对象
- 服务器端根据 name 为 JSESSIONID 的 Cookie 的 value(sessionId),在服务器内查找 Session 对象,从而跟踪到用户状态
Cookie与Session区别
- 存储方式:Cookie是String类型;Session是Object类型
- 存储位置:Cookie存放在客户端浏览器;Session存放在服务器
- 安全性:Cookie明文存放在客户端,易泄露,安全性弱; Session存在服务器,对客户端透明,安全性强
- 有效期:
Cookie保存在硬盘,只需设置MaxAge属性值为比较大的正整数,即使关闭浏览器,Cookie还是存在的
Session保存在服务器,设置MaxInactiveInterval属性值{Session的生命周期是间隔变化的,比如每访问一次就重新记时,若整个间隔时间内没有访问则失效}来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的MaxAge属性为-1(表示仅当前浏览器内有效,并且各浏览器窗口间不共享),如果关闭了浏览器,该Session虽然没有从服务器中消亡,但是会失效 - 对服务器的负担:
Cookie:保存在客户端上,不占用服务器资源
Session:保存在服务器上,用户都会产生一个Sessioon,如果并发访问的用户非常多,会消耗大量内存
Session和Cookie如何选择
- 数据复杂性:首选Session。Cookie只能存储ASCII码字符串,而Session则可以存储任何类型的数据
- 安全性:首选Session。Cookie存在浏览器,容易被恶意查看。如果非要将一些隐私数据存在Cookie中,
可以将Cookie值进行加密,然后在服务器进行解密 - 大型网站,不建议将所有用户信息都存储到Session中。用户所有信息都存在Session中,开销是非常大
登录信息放在Session还是Cookie?
- Session保存在服务器中,更加安全。但如果在高并发情况下,用户群体多的话,服务器压力很大(适合用户群体少的后台管理系统)
- Cookie保存在浏览器端,京东、淘宝等大型网站都将用户信息保存在Cookie中。虽然不安全,但是我们可以对信息加密或者将涉及隐私的信息不保存到Cookie,不存在服务器压力
Cookie,sessionStorage和localStorage区别
-
同:都存储在客户端
-
异:
- 存储大小:
Cookie数据大小不能超过4K
sessionStorage和localStorage也有存储大小的限制,但比Cookie大得多,可以达到5M或更大 - 有效时间:
localStorage:存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
sessionStorage:数据在当前浏览器窗口关闭后自动删除
Cookie:设置的Cookie过期时间之前一直有效,即使窗口或浏览器关闭 - 数据与服务器之间的交互方式:
cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
- 存储大小:
HTTP缓存
HTML如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载
图片都是HTTPS连接并且在同一个域名下,那么浏览器在SSL握手之后会和服务器商量能不能用HTTP2,如果能的话就使用Multiplexing功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个TCP连接去获取,但是可以确定的是 Multiplexing很可能会被用到。如果发现用不了HTTP2呢?或者用不了HTTPS,所以也就是只能使用HTTP/1.1。那浏览器会在一个HOST上建立多个TCP连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求
常用的端口及协议
TCP
- Telnet:终端模拟:23
- FTP:文件传输协议:20、21
- HTTP:超文本传输协议:80
- HTTPS:超文本传输安全协议:443
- SSH:远程连接服务:22
- TCP服务端:8080
- Nginx服务器:8888
- MySQL:默认端口是3306
- Tomcat:默认端口是8080
- ORACLE:默认端口1521、1526
ping命令是基于哪层协议
- 作用:ping命令用来探测本机与网络中另一主机之间是否可达,如果两台主机之间ping不通,则表明这两台主机不能建立起连接
- 原理:ping命令基于网络层的ICMP协议(Internet控制报文协议)工作
ping命令会发送一份ICMP回显请求报文给目标主机,并等待目标主机返回 CMP回显应答报文。因为ICMP协议会要求目标主机在收到消息之后,必须返回ICMP应答消息给源主机,如果源主机在一定时间内收到了目标主机的应答,则表明两台主机之间网络是可达的
HTTP中重定向和请求转发的区别
本质区别:转发是服务器行为,重定向是客户端行为
重定向:两次请求,浏览器地址发生变化,可以访问自己web之外的资源,传输的数据会丢失
请求转发:一次请求,浏览器地址不变,访问的是自己本身的web资源,传输的数据不会丢失
HTTP如何保证安全传输
- 重要的数据,要加密:防止被抓包监听
- 非重要数据,要签名:防止内容被篡改
- 登录态怎么做:token
HTTP如何传输大文件
-
数据压缩
浏览器在发送请求时都会带着 Accept-Encoding 头字段,里面是浏览器支持的压缩格式列表,例如 gzip、deflate、br 等,这样服务器就可以从中选择一种压缩算法,放进 Content-Encoding 响应头里,再把原数据压缩后发给浏览器。gzip 等压缩算法通常只对文本文件有较好的压缩率,而图片、音频视频等多媒体数据本身就已经是高度压缩的,再用 gzip 处理也不会变小。如在 Nginx 里就会使用 gzip on 指令,启用对 text/html 的压缩
-
分块传输
大文件整体不能变小,那就把它拆开,分解成多个小块,把这些小块分批发给浏览器,浏览器收到后再组装复原。在 HTTP 协议里就是 chunked 分块传输编码,在响应报文里用头字段 Transfer-Encoding: chunked 来表示,意思是报文里的 body 部分不是一次性发过来的,而是分成了许多的块(chunk)逐个发送
https://www.cnblogs.com/traditional/p/15373999.html
HTTPS
HTTP和HTTPS区别
HTTPS相对于HTTP有哪些不同呢?其实就是在HTTP跟TCP中间加多了一层加密层 TLS/SSL
SSL(Secure Socket Layer,安全套接字层):保证进程和服务器间发送数据私密性、完整性、可鉴别性的协议
TLS(Transport Layer Security,传输层安全):SSL的标准化,更为安全的升级版SSL
申请证书 | 传输方式 | 连接端口 | |
---|---|---|---|
HTTP | 无需 | 运行在 TCP 之上,明文传输 | 80 |
HTTPS | 申请证书,需要支付一定费用 | 运行在 SSL/TLS 之上,SSL/TLS 运行在 TCP 之上,加密传输 | 443 |
HTTPS如何保证数据安全传输
Nginx 安装 SSL 配置 HTTPS 超详细完整全过程
HTTPS采用混合加密机制,使用非对称密钥加密传输,对称密钥来保证密钥传输过程的安全,使用对称密钥加密进行通信
- 浏览器向服务器端发起 SSL 连接请求,将支持的加密算法信息发送给服务器
- 服务器选择一套浏览器支持的加密算法,以(公钥)证书的形式回发浏览器
- 浏览器验证证书合法性,使用伪随机数生成器生成通信加密所使用的对称密钥,再用证书公钥对对称秘钥进行加密,发送给服务器
- 服务器使用私钥解密,从而得到对称密钥,验证哈希,加密响应消息回发浏览器
- 浏览器解密响应消息,并对消息进行验证,之后进行加密进行数据传输
HTTPS都使用哪些加密的算法?
- 对称加密(Symmetric Key Algorithms)
- 特点:
- 加密方和解密方使用同一个密钥
- 加解密的速度比较快,适合数据比较长时使用
- 密钥传输的过程不安全,且容易被破解,密钥管理也比较麻烦
- 实现:
- DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合
- 3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高
- AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高
- 特点:
- 非对称加密(Asymmetric Key Algorithms)
- 特点:
- 算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。把密钥分为公钥和私钥
- 实现:
- RSA:支持变长密钥的公共密钥算法,需要加密的文件块的长度也是可变的
- DSA(Digital Signature Algorithm):数字签名算法
- ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学
- 特点:
对称加密算法加密数据 + 非对称加密算法交换密钥 + 数字证书验证身份 = 安全
HTTPS加密算法用在哪个步骤?
SSL / TLS
HTTPS加密流程
- 首先,客户端发起握手请求,以明文传输请求信息,包含版本信息,加密-套件候选列表,压缩算法候选列表,随机数,扩展字段等信息(这个没什么好说的,就是用户在浏览器里输入一个HTTPS网址,然后连接到服务端的443端口)
- 服务端的配置,采用HTTPS协议的服务器必须要有一套数字证书,可以自己制作,也可以向组织申请。区别就是自己颁发的证书需要客户端验证通过,才可以继续访问,而使用受信任的公司申请的证书则不会弹出提示页面。
这套证书其实就是一对公钥和私钥。
如果对公钥不太理解,可以想象成一把钥匙和一个锁头,只是世界上只有你一个人有这把钥匙,你可以把锁头给别人,别人可以用这个锁把重要的东西锁起来,然后发给你,因为只有你一个人有这把钥匙,所以只有你才能看到被这把锁锁起来的东西。 - 服务端返回协商的信息结果,包括选择使用的协议版本 version,选择的加密套件 cipher suite,选择的压缩算法 compression method、随机数 random_S 以及证书。(这个证书其实就是公钥,只是包含了很多信息,如证书的颁发机构,过期时间等等)
- 客户端验证证书的合法性,包括可信性,是否吊销,过期时间和域名。(这部分工作是由客户端的SSL/TLS来完成的,首先会验证公钥是否有效,比如颁发机构,过期时间等等,如果发现异常,则会弹出一个警示框,提示证书存在的问题。如果证书没有问题,那么就生成一个随机值。然后用证书(也就是公钥)对这个随机值进行加密。就好像上面说的,把随机值用锁头锁起来,除非有钥匙,不然看不到被锁住的内容)
- 客户端使用公匙对对称密匙加密,发送给服务端。(这部分传送的是用证书加密后的随机值,目的是让服务端得到这个随机值,以后客户端和服务端的通信就可以通过这个随机值来进行加密解密了)
- 服务器用私钥解密,拿到对称加密的密匙。(服务端用私钥解密后,得到了客户端传过来的随机值,然后把内容通过该随机值进行对称加密,将信息和私钥通过某种算法混合在一起,这样除非知道私钥,不然无法获取内容,而正好客户端和服务端都知道这个私钥,只要加密算法够彪悍,私钥够复杂,数据就够安全)
- 传输加密后的信息,这部分信息就是服务端用私钥加密后的信息,可以在客户端用随机值解密还原
- 客户端解密信息,客户端用之前生产的私钥解密服务端传过来的信息,于是获取了解密后的内容。整个过程第三方即使监听到了数据,也束手无策
从网页上下载一个安装包如何判断是否被篡改过?
HTTPS 如何保证安全?
结合两种加密⽅式,将对称加密的密钥使⽤⾮对称加密的公钥进⾏加密,然后发送出去,接收⽅使⽤私钥进⾏解密得到对称加密的密钥,然后双方可以使⽤对称加密来进⾏沟通。
- 中间⼈问题: 如果此时在客户端和服务器之间存在⼀个中间⼈,这个中间⼈只需要把原本双⽅通信互发的公钥,换成⾃⼰的公钥,这样中间⼈就可以轻松解密通信双⽅所发送的所有数据——需要⼀个安全的第三⽅颁发证书(CA),证明身份的身份,防⽌被中间⼈攻击。 证书中包括:签发者、证书⽤途、使⽤者公钥、使⽤者私钥、使⽤者的 HASH 算法、证书到期时间等
- 篡改CA证书,那么身份证明是不是就⽆效了?这个证明就白买了——数字签名,就是用 CA 自带的 HASH 算法对证书的内容进行 HASH 得到⼀个摘要,再用 CA 的私钥加密,最终组成数字签名。当别⼈把他的证书发过来的时候,我再用同样的 Hash 算法,再次生成消息摘要,然后用 CA 的公钥对数字签名解密,得到 CA 创建的消息摘要,两者⼀比,就知道中间有没有被人篡改了。这个时候就能最大程度保证通信的安全
本地公钥被篡改怎么办?
简述 HTTPS 中间人攻击
中间人攻击过程如下:
- 服务器向客户端发送公钥
- 攻击者截获公钥,保留在自己手上
- 然后攻击者自己生成一个【伪造的】公钥,发给客户端
- 客户端收到伪造的公钥后,生成加密 hash 值发给服务器
- 攻击者获得加密 hash 值,用自己的私钥解密获得真秘钥
- 同时生成假的加密 hash 值,发给服务器
- 服务器用私钥解密获得假秘钥
- 服务器用假秘钥加密传输信息
防范方法:
- 服务端在发送浏览器的公钥中加入 CA 证书,浏览器可以验证 CA 证书的有效性
浏览器
CORS跨域请求
跨域行为是浏览器行为,一个跨域请求实际已经发送到服务端,服务端也返回了消息,然而浏览器在接收到返回信息的时候,发现该信息不是同源请求且没有允许跨域的限制,所以在解析消息的将该条消息屏蔽同时在控制台报错
CORS跨域解决
- 利用浏览器允许标签的
跨域
这一特性,例如JOSNP
,但是JSONP
只能使用get
方法请求数据 - 'Access-Control-Allow-Origin':'*' //允许所有站点跨域请求,也可以设置成某一个具体站点
CORS跨域限制
主要包括 methods content-type 和 请求头的限制
允许方法:默认允许方法 GET HEAD POST,其他的方法 PUT DELETE 默认是不允许的
允许Content-Type
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
除了这三种,其他的 Content-Type 也需要使用预请求验证后,才能发送
其他限制
- 请求头限制,自定义的请求头默认是不允许的,也需要验证;官方文档,关于请求头的详细信息https://fetch.spec.whatwg.org/#cors-safelisted-request-header
- XMLHttpRequestUpload 对象均没有注册任何事件监听器(很少用)
- 请求中没有使用 ReadableStream 对象(很少用)
CORS预请求
缓存头Cache-Control使用
- 可缓存性
public
private
no-cache - 到期
max-age=<seconds>
s-maxage=<seconds>
max-stale=<seconds> - 重新验证
must-revalidate
proxy-revalidate - 其他
no-store
no-transform
缓存验证Last-Modified和Etag
- Last-Modified
上次修改时间
配合If-Modified-Since或者If-Unmodified-Since使用
对比上次修改时间以验证资源是否需要更新 - Etag
数据签名
配合lf-Match或者lf-Non-Match使用
对比资源的签名判断是否使用缓存
CSP
Content-Security-Policy,内容安全策略
- 作用
限制资源获取
报告资源获取越权 - 限制方式
default-src限制全局
制定资源类型:connect-src、img-src、style-src、manifest-src、font-src、media-src、frame-src、script-src
在浏览器中输入URL后,执行过程
HTTP请求的过程:
- 判断是否需要跳转页面Redirect
- 查看是否存在缓存
- DNS域名解析:获取对应的 IP 地址
- 查询DNS缓存:浏览器缓存 --> 操作系统缓存 --> 操作系统的hosts文件
- 本地域名服务器(递归查询)
- TCP三次握手建立连接
- 客户端发送HTTP请求的数据包
- 服务器接收到数据包,处理并返回请求响应的内容
- 浏览器解析HTML代码,并请求HTML代码中的资源
- TCP断开(四次挥手)
- 浏览器渲染页面呈现给用户
从输入 URL 到页面加载完成的过程(详细版)
- 在浏览器地址栏输入 URL
- 判断是否有永久重定向(301)
- 浏览器查看资源是否有强缓存,若命中强缓存就直接从缓存中使用,若协商缓存则需要到服务器进行校验资源是否可用
HTTP1.0 提供 expires,值为一个绝对时间表示缓存过期时间
HTTP1.1 增加了一个 cache-control:max-age,值为以秒为单位的最大缓存过期时间。还有 no-cache,no-store,分别表示可以缓存但会立即失效和不能缓存- 浏览器解析 URL 获取协议,主机,端口,path
- 浏览器组装一个 HTTP(GET)请求报文
- DNS 解析
- 查找浏览器缓存
- 查找本机缓存
- 查找 hosts 文件
- 路由器缓存
- ISP DNS 缓存
- DNS 查询(递归查询、迭代查询)
- 端口建立 TCP 连接(三次握手)
- TCP 连接建立后发起 HTTP 请求
- 服务器接收到请求并解析,将请求转发到服务程序
- 服务器检查 HTTP 请求头部是否有缓存验证信息,如果缓存未过期,返回 304 状态码
- 处理程序读取完整请求并准备 HTTP 响应,同时可能需要查询数据库等操作
- 服务器将相应报文通过 TCP 连接发送会浏览器
- 接收到 HTTP 响应,根据情况选择是否关闭 TCP 连接,若关闭的话四次挥手
- 浏览器接收到服务端的响应报文后,会检查响应状态码,根据不同的状态码处理不同的情况
- 如果资源可以缓存,进行缓存
- 将响应内容进行解码
- 根据资源类型决定如何处理
- 若资源类型为 html 类型,解析 html 文档,构建 DOM 树,并下载相关资源,构造 CSSOM 树,执行 js 脚本
- 构造 DOM 树,解析过程中如果遇到图片、样式表、js 文件便启动下载
- 构建 CSSOM 树
- 根据 DOM 树和 CSSOM 树构建渲染树
从 DOM 树的根节点遍历所有可见节点。
对每一个节点找到恰当的 CSSOM 规则并应用
发布可视节点的内容和计算样式- js 脚本解析
浏览器创建 document 对象并解析 html,将解析的文本和节点添加到文档中- html 解析器遇到没有 defer 和 async 属性的 script 时,将他们添加到文档中,然后去执行脚本语句。在脚本下载和执行时 html 解析器会暂停。直到 script 下载和执行完毕
- 当解析器遇到 async 属性的 script 时,开始下载脚本但会继续解析文档,当脚本下载完毕时就会立刻回过头去执行该脚本,但是解析器不会停下来等它下载
- 当解析器遇到 defer 属性的 script 时,defer 脚本会在文档解析完毕时按照顺序执行,并且可以访问完整文档
- 浏览器在 document 对象上触发 DOMContentLoaded 事件
- 此时文档完全解析完成,浏览器可能还在等待图片等内容加载,等待这些内容完成载入并且所有异步脚本完成载入和执行之后,window 会触发 loaded 事件
- 显示页面(html 解析过程中会逐步显示页面)
浏览器的渲染过程
- 首先解析收到的文档,根据文档定义构建一棵 DOM 树,DOM 树是由 DOM 元素及属性节点组成的,然后对 CSS 进行解析,生成 CSSOM 规则树
- 根据 DOM 树和 CSSOM 规则树构建渲染树。渲染树的节点被称为渲染对象,渲染对象是一个包含有颜色和大小等属性的矩形,渲染对象和 DOM 元素相对应,但这种对应关系不是一对一的,不可见的 DOM 元素不会被插入渲染树。还有一些 DOM 元素对应几个可见对象,它们一般是一些具有复杂结构的元素,无法用一个矩形来描述
- 当渲染对象被创建并添加到树中,它们并没有位置和大小,所以当浏览器生成渲染树以后,就会根据渲染树来进行布局(也可以叫做回流)。这一阶段浏览器要做的事情是要弄清楚各个节点在页面中的确切位置和大小。通常这一行为也被称为“自动重排”
- 布局阶段结束后是绘制阶段,遍历渲染树并调用渲染对象的 paint 方法将它们的内容显示在屏幕上,绘制使用 UI 基础组件
浏览器缓存
-
强缓存:浏览器在加载资源时,会先根据本地缓存资源的 header 中的信息判断是否命中强缓存,如果命中则直接使用缓存中的资源不会再向服务器发送请求。对于强制缓存,服务器响应的 header 中会用两个字段来表明——Expires和Cache-Control
- Expires:Exprires 的值为服务端返回的数据到期时间。当再次请求时的请求时间小于返回的此时间,则直接使用缓存数据。但由于服务端时间和客户端时间可能有误差,这也将导致缓存命中的误差,另一方面,Expires 是 HTTP1.0 的产物,故现在大多数使用 Cache-Control 替代。如果 cache-control 与 expires 同时存在的话,cache-control 的优先级高于 expires
- Cache-Control:
private:客户端可以缓存
public:客户端和代理服务器都可以缓存
max-age=t:缓存内容将在 t 秒后失效
no-cache:需要使用协商缓存来验证缓存数据
no-store:所有内容都不会缓存
-
协商缓存:当强缓存没有命中的时候,浏览器会发送一个请求到服务器,服务器根据请求头中的部分信息来判断是否命中缓存。如果命中,则返回 304,告诉浏览器资源未更新,可使用本地的缓存
- Last-Modified:假设此时我们的协商缓存用 Last-Modified 来判断。当浏览器第一次发送请求时,服务器返回资源并返回一个 Last-Modified 的值给浏览器。这个 Last-Modified 的值给到浏览器之后,浏览器会通过 If-Modified-Since 的字段来保存 Last-Modified 的值,且 If-Modified-Since 保存在请求头当中。之后当浏览器再次发送请求时,请求头会带着 If-Modified-Since 的值去找服务器,服务器此刻就会匹配浏览器发过来的 If-Modified-Since 是否和自己最后一次修改的 Last-Modified 的值相等。如果相等,则返回 304,表示资源未被修改;如果不相等,则返回 200,并返回资源和新的 Last-Modified 的值
- Etag:假设此时我们的协商缓存用 Etag 来判断。当浏览器第一次发送请求时,服务器返回资源并返回一个 Etag 的值给浏览器。这个 Etag 的值给到浏览器之后,浏览器会通过 If-None-Match 的字段来保存 Etag 的值,且 If-None-Match 保存在请求头当中。之后当浏览器再次发送请求时,请求头会带着 If-None-Match 的值去找服务器,服务器此刻就会匹配浏览器发过来的 If-None-Match 是否和自己最后一次修改的 Etag 的值相等。如果相等,则返回 304,表示资源未被修改;如果不相等,则返回 200,并返回资源和新的 Etag 的值
刷新操作方式,对缓存的影响
- 正常操作
定义: 地址栏输入 url,跳转链接,前进后退等
对缓存的影响: 强制缓存有效,协商缓存有效- 手动刷新
定义:F5,点击刷新按钮,右击菜单刷新
对缓存的影响: 强制缓存失效,协商缓存有效- 强制刷新
定义:ctrl + F5
对缓存的影响: 强制缓存失效,协商缓存失效
WEB安全防范
XSS攻击
XSS攻击简介
XSS攻击:跨站脚本攻击,是一种代码注入攻击。攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如 cookie 等。本质是因为网站没有对恶意代码进行过滤,与正常的代码混合在一起了,浏览器没有办法分辨哪些脚本是可信的,从而导致了恶意代码的执行
攻击者可以通过这种攻击方式可以进行以下操作:
- 获取页面的数据,如 DOM、cookie、localStorage
- DOS 攻击,发送合理请求,占用服务器资源,从而使用户无法访问服务器
- 破坏页面结构
- 流量劫持(将链接指向某网站)
XSS攻击类型
XSS 可以分为存储型、反射型和 DOM 型:
- 存储型:恶意脚本会存储在目标服务器上,当浏览器请求数据时,脚本从服务器传回并执行
- 反射型:攻击者诱导用户访问一个带有恶意代码的 URL 后,服务器端接收数据后处理,然后把带有恶意代码的数据发送到浏览器端,浏览器端解析这段带有 XSS 代码的数据后当做脚本执行,最终完成 XSS 攻击
- DOM型:通过修改页面的 DOM 节点形成的 XSS
防御XSS攻击
- 可以从浏览器的执行来进行预防,一种是使用纯前端的方式,不用服务器端拼接后返回(不使用服务端渲染)。另一种是对需要插入到 HTML 中的代码做好充分的转义。对于 DOM 型的攻击,主要是前端脚本的不可靠而造成的,对于数据获取渲染和字符串拼接的时候应该对可能出现的恶意代码情况进行判断。
- 使用 CSP,CSP 的本质是建立一个白名单,告诉浏览器哪些外部资源可以加载和执行,从而防止恶意代码的注入攻击(CSP 指的是内容安全策略,它的本质是建立一个白名单,告诉浏览器哪些外部资源可以加载和执行。我们只需要配置规则,如何拦截由浏览器自己来实现。通常有两种方式来开启 CSP,一种是设置 HTTP 首部中的 Content-Security-Policy,一种是设置 meta 标签的方式)
- 对一些敏感信息进行保护,比如 cookie 使用 http-only,使得脚本无法获取。也可以使用验证码,避免脚本伪装成用户执行一些操作
SYN攻击
SYN攻击简介
服务器端的资源分配是在第3次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击
SYN攻击原理:Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN攻击是一种典型的DDoS攻击
防御SYN攻击的方法:
- 超时(SYN Timeout)时间
- 增加最大半连接数
- 过滤网关防护
- SYN Cookies技术:用一个 Cookie 来响应TCP SYN请求的 TCP 实现。当 Server 接收到一个 Client 的 SYN 数据包时,Server 通过特定的算法把 半开连接信息 编码成“Cookie”,随 SYN-ACK 包一同发给Client,这样在连接完全建立前 B 不保存任何信息。 缺点:最明显的就是B不保存连接的半开状态,就丧失了重发 SYN-ACK 消息的能力,这一方面会降低正常用户的连接成功率
文件上传漏洞是如何发生的?如何防范?
文件上传漏洞指的是用户上传一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力
防范文件上传漏洞:
- 文件上传的目录设置为不可执行
- 判断文件类型:在判断文件类型的时候,可以结合使用MIME Type,后缀检查等方式。因为对于上传文件,不能简单地通过后缀名称来判断文件的类型,因为攻击者可以将可执行文件的后缀名称改为图片或其他后缀类型,诱导用户执行
- 对上传的文件类型进行白名单校验,只允许上传可靠类型
- 限制上传文件的大小
- 单独设置文件服务器的域名
CSRF攻击
CSRF攻击简介
CSRF 攻击:跨站请求伪造攻击,攻击者诱导用户进入一个第三方网站,然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态,那么攻击者就可以利用这个登录状态,绕过后台的用户验证,冒充用户向服务器执行一些操作。本质是利用 cookie 会在同源请求中携带发送给服务器的特点,以此来实现用户的冒充
CSRF攻击类型
常见的 CSRF 攻击有三种:
- GET 类型的 CSRF 攻击,比如在网站中的一个 img 标签里构建一个请求,当用户打开这个网站的时候就会自动发起提交。
- POST 类型的 CSRF 攻击,比如构建一个表单,然后隐藏它,当用户进入页面时,自动提交这个表单。
- 链接类型的 CSRF 攻击,比如在 a 标签的 href 属性里构建一个请求,然后诱导用户去点击
防御CSRF攻击
- 进行同源检测,服务器根据 http 请求头中 origin 或者 referer 信息来判断请求是否为允许访问的站点,从而对请求进行过滤。当 origin 或者 referer 信息都不存在的时候,直接阻止请求。这种方式的缺点是有些情况下 referer 可以被伪造,同时还会把搜索引擎的链接也给屏蔽了。所以一般网站会允许搜索引擎的页面请求,但是相应的页面请求这种请求方式也可能被攻击者给利用。(Referer 字段会告诉服务器该网页是从哪个页面链接过来的)
- 使用 CSRF Token 进行验证
服务器向用户返回一个随机数 Token,当网站再次发起请求时,在请求参数中加入服务器端返回的 token,然后服务器对这个 token 进行验证。这种方法解决了使用 cookie 单一验证方式时,可能会被冒用的问题,但是这种方法存在一个缺点就是,我们需要给网站中的所有请求都添加上这个 token,操作比较繁琐。还有一个问题是一般不会只有一台网站服务器,如果请求经过负载平衡转移到了其他的服务器,但是这个服务器的 session 中没有保留这个 token 的话,就没有办法验证了。这种情况可以通过改变 token 的构建方式来解决
JavaWeb
RESTful的理解
RESTful(Representational State Transfer,表现层状态转化)架构,目前最流行的一种互联网软件架构。结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
-
资源(Resources)
"表现层"其实指的是"资源"(Resources)的"表现层"。所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。所谓"上网",就是与互联网上一系列的"资源"互动,调用它的URI
-
表现层(Representation)
"资源"是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。URI只代表资源的实体,不代表它的形式。严格地说,有些网址最后的".html"后缀名是不必要的,因为这个后缀名表示格式,属于"表现层"范畴,而URI应该只代表"资源"的位置。它的具体表现形式,应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述
-
状态转化(State Transfer)
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
RESTful架构:
- 每一个URI代表一种资源
- 客户端和服务器之间,传递这种资源的某种表现层
- 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"
设计误区:
-
URI包含动词
- 因为"资源"表示一种实体,所以应该是名词,URI不应该有动词,动词应该放在HTTP协议中
- 某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示show
- 如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:POST /accounts/1/transfer/500/to/2。正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务
POST /transaction HTTP/1.1 Host: 127.0.0.1 from=1&to=2&amount=500.00
-
URI中加入版本号
因为不同的版本,可以理解成同一种资源的不同表现形式,所以应该采用同一个URI。版本号可以在HTTP请求头信息的Accept字段中进行区分
http://www.example.com/app/1.0/foo --> Accept: vnd.example-com.foo+json; version=1.0 http://www.example.com/app/1.1/foo --> Accept: vnd.example-com.foo+json; version=1.1
Servlet
Servlet的生命周期
- Servlet初始化:init()
- Servlet处理请求:service(),根据请求的不同调用不同的 doGet()/doPost()方法
- Servlet销毁:destroy()
- Servlet由JVM的垃圾回收器进行垃圾回收
Servlet API 中 forward() 与 redirect()的区别?
- forward():仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址
- redirect():完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接。这样,从浏览器的地址栏中可以看到跳转后的链接地址。所以,前者更加高效,在前者可以满足需要时,尽量使用forward()方法,并且,这样也有助于隐藏实际的链接。在有些情况下,比如,需要跳转到一个其它服务器上的资源,则必须使用 sendRedirect()