网络层
网络层的作用
网络层只提供简单灵活、无连接的,尽最大努力交付的数据报服务,不提供网络质量的保证。
虚拟互连网络
虚拟互连网络通过中间设备和IP协议使得存在异构的物理网络"统一化"
地址解析协议 ARP
ARP解决了什么问题
已知一个机器的IP地址,如何找出其相应的硬件地址?ARP就是解决这个问题,即从网络层使用的IP地址,解析出数据链路层使用的硬件地址。
原理
- 不管网络层使用什么协议,在实际网络链路上传输数据帧时,还是要用硬件地址。
- 每一个主机或路由器都设有一个ARP高速缓存,里面有所在局域网上各主机和路由器的IP地址到硬件地址的映射表。
运输层
TCP UDP区别
- TCP是面向连接的协议,提供面向连接的服务,仅支持单点传播,提供可靠服务
- UDP是无连接协议,提供面向无连接服务,支持单播,多播,广播,提供不可靠服务
端口
首先,计算机之间通信实际上是不同计算机上的进程进行通信,而在计算机中我们用进程标识符来标记不同进程,但由于不同操作系统的进程标识符格式不同,且软件每次运行进程可能会改变,为了维护TCP/IP体系,我们必须用统一方法对进程进行标识,这就引出了端口。
UDP特点
- UDP是无连接的,发送数据前不需要建立连接
- UDP使用尽最大努力交付,即不可靠交付
- UDP是面向报文的,应用层给UDP多长的报文,UDP就照样发送
- UDP没有拥塞控制
- UDP支持单播,多播,广播交互通信
- UDP首部开销小
TCP特点
- TCP是面向连接的协议
- TCP提供可靠交付,即无差错、不丢失、不重复且按需到达
- TCP支持全双工通信
- TCP只支持点对点连接
- TCP是面向字节流的,即虽然应用程序与TCP交互为一个个数据块,但TCP仅将这些数据块看作字节流。
socket套接字
每一条TCP有两个端点,TCP连接的端点就叫socket套接字,它是由IP地址和端口号拼接而成的
可靠传输的工作原理
- 停止等待协议,停止等待协议就是每发送完一个分组就停止发送,等待确认。收到确认后再发下一个分组。
缺点:信道利用率较低
- 连续ARQ协议
连续ARQ协议就是每一端都维护一个发送窗口和接收窗口,发送方一次可以发出多个组,使用滑动窗口协议控制发送方和接收方所能接收到的分组数量及编号。
TCP流量控制--滑动窗口协议
假设有一个发送窗口最大长度为5,一个最大长度为3的接收窗口。发送窗口从1到5开始发送,每发送一个数据块往前移动一个单位,并减少一个单位自身长度,当收到接收窗口的确认后,接收窗口往前移动,发送窗口长度增加,注意,发送窗口无需等待接收窗口的确认,只需进行发送。
TCP的流量控制
就是维护接收窗口剩余大小,如果为0,只允许发送窗口超时重传旧的数据,不能发送新的数据。
TCP的拥塞控制
发送方维护一个拥塞窗口,就跟上面滑动窗口差不多,发送的多少取发送窗口和拥塞窗口的最小值
四个拥塞控制算法:
- 慢开始:由小到大逐渐增加拥塞窗口大小(指数增加)
- 拥塞避免:让拥塞窗口缓慢增大,每经过一个传播轮次就加一
- 快重传:一连收到三个重复确认就知道接收方确实没收到报文段,应当立即重传。
- 快恢复:
TCP三次握手
TCP建立连接的过程叫做握手,握手需要在客户和服务端之间交换三个TCP报文,叫做三次握手
上图第一个TCP报文发送时,会将SYN标识开启,意为客户端想和服务端建立同步连接,同时,报文内还有一个重要字段叫做sequence字段(随机生成),用于判断不同信息;第二个TCP报文发送时会开启SYN和ACK标识,ACK意为确认,合起来就是确认同步,同时服务端还要生成自己的sequence序号,并生成一个确认号,值为客户端报文的序号+1,这样客户端就能通过-1确认是否为自己的报文。最后,客户端还要再发送一个TCP报文,用于确认服务端发送的确认同步报文,所以会再次建立一个TCP连接,加上ACK标识符,同理客户端也会生成自己的序号和确认号,这里的序号为对方的确认号,这里的确认号为对方的序号+1。
TCP四次挥手
数据传输结束后,双方都可以释放连接,这个过程被称为四次挥手,下图假设客户端释放连接
首先客户端发送报文,添加上ACK和FIN标识符,意为结束确认,表示要结束连接,并添加序号和确认号字段;第二步服务端发送报文,添加ACK标识符,意为收到结束请求,添加序号,值为对方确认号,添加确认号,值为对方序号+1;但此时,虽然客户端请求结束连接,但服务端仍可能有未发送完的数据,所以需要在服务端发送完数据后,服务端再次发送报文,请求结束连接,但此时的序号和确认号不需要改变,因为没有一来一回,同理,客户端发送确认结束的报文;共四个报文,四次挥手。
http相关
get与post区别
- 从使用方面讲,get一般用于获取数据,post一般用于向服务端发送数据,get传递参数时一般用params参数,而post一般把传递的数据放在body中。
- 从参数长度方面讲,由于浏览器对url长度的限制,所以get请求传递的数据量较小,而post请求则没有限制
- 从编码方式来讲,get请求只能通过application/x-www-form-urlencoded,post则可以以formdata或url格式编码。
- 从缓存机制上讲,get请求会被浏览器主动缓存,请求参数也会被浏览器历史记录完整记载,post则不会
常见的状态码
- 1xx:消息状态码 100continue
- 2xx:成功状态码 200为ok请求成功,201created成功请求并创建新资源,202accepted已接受请求但未完成,204无内容,但服务器成功处理
- 3xx:重定向状态码 304未修改,所请求资源未修改
输入url回车后发生什么
- 执行DNS域名解析,获得url域名对应的ip地址
- 封装http数据包和tcp请求数据包,建立tcp连接
- 发送http请求,服务端进行处理后将结果封装成http请求包,返回给客户端
- 服务端与客户端交互完成,断开http连接
- 浏览器解析HTML、CSS和JS文件,解析html生成dom树,解析css生成cssom树,整合到一起生成render树,然后将整合好的DOM放到对应位置,最后渲染页面。
HTTP
基础概念
请求报文
请求报文结构:
- 第一行,请求方法、URL、协议版本
- 接下来多行:多个请求头,每个请求头都是key:value的形式
- 空一行 区分请求头和请求体
- 请求体,即发送给服务端的数据
响应报文
- 第一行:协议版本,状态码,描述,如HTTP/1.1 200 OK
- 下面多行:响应头,也是key:value形式
- 空一行,分隔开首部和内容主体
- 响应的内容主体
URL URI
URI是统一资源标识符,URL是统一资源定位符,URL是URI的子集,区别在于URI是用来定义一个资源的名称,URL则在URI的基础上增加了定位能力,URI包括URL和URN(统一资源名称)
HTTP方法
- GET 用于获取资源
- HEAD 类似GET,但不会返回报文实体主体部分,一般用于验证URL的有效性和资源更新的时间日期等。
- POST 一般用于传输数据 与GET区别后面补充
- PUT DELETE 一个用于上传文件,一个用于删除文件,由于这两个方法自身不带有验证机制,任何人都可以上传删除,所以一般不使用
- PATCH 用于修改资源,PUT也可以原来修改资源,不过是整个替换,PATCH支持部分修改
- OPTIONS 发送复杂请求前会发送OPTIONS查询指定url能够支持的方法
- CONNECT 要求在与代理服务器通信时建立隧道
- TRACE 追踪路径 服务器会将通信路径返回给客户端,一般不使用,容易遭受攻击
HTTP状态码
1XX 信息
- 100 Continue 请求正在处理
2XX 请求成功
- 200 OK
- 204 No Content 请求成功但响应报文不包含实体的主体部分。
- 206 Partial Content 表示客户端进行了范围请求,服务端返回了由Content-Range指定范围的主体内容
3XX 重定向
- 301 永久性重定向
- 302 临时性重定向
- 303 与302有相同功能,但303会明确要求客户端采用GET方法获取资源 注:HTTP协议不允许301、302状态下重定向把POST方法改成GET方法,但大部分浏览器会在301、302、303状态下重定向把POST方法改成GET方法
- 304 如果请求报文中包含如 IF-Match, If-Range等条件,如果不满足条件服务端就会返回304
- 307 与302类似,但不会要求重定向请求的POST方法改为GET
4XX 客户端错误
- 400 Bad Request 请求报文中存在语法错误
- 401 Unauthorized 请求需要认证信息,如果之前已经发送过一次请求,则说明认证失败
- 403 Forbidden 请求被拒绝
- 404 Not Found
- 415 Unsupport Media Type 请求体的格式错误
5XX 服务端错误
- 500 Internal Server Error 服务器在执行请求时发生错误
- 503 Service Unavailable 服务器暂时处于超负载或者在停机维护
实际应用
连接管理
- 短连接与长连接
在HTTP/1.1前,默认是短连接的,也就是说每进行一次HTTP通信就要建立一个TCP连接,这样开销很大,这也引出了长连接,即建立一次TCP连接可以进行多次的HTTP通信。HTTP/1.1默认长连接,如果要断开连接,使用Connection:close;HTTP/1.1前默认短连接,如果要使用长连接,则使用Connection:Keep-Alive。 - 流水线 默认情况下,HTTP请求是按顺序发出的,下一个请求需要收到请求响应后才发出,这可能会导致需要等待很长时间,流水线就是在同一条长连接上连续发出请求,而不用等待响应返回,这样可以减少延迟。
Cookie
HTTP协议是无状态的,主要是为了使HTTP协议尽可能的简单,为了保存状态信息,HTTP/1.1引入了cookie
Cookie是服务端发送到客户端并保存在本地的一小块数据,他会在浏览器向同一服务器发送请求时携带。
- 用途
- 用户信息保存
- 个性化设置
- 。。。
- 创建过程
服务端发送的响应报文中会包含
Set-Cookie字段,客户端会把字段的值保存到本地,下次向同一服务器发送请求时会自动携带这个cookie - 分类
- 会话期cookie:浏览器关闭后自动删除
- 持久性cookie:设置了过期时间Expires和有效期max-age后就是持久cookie,同样是在响应报文的set-cookie字段设置
- 作用域
Domain标识指定哪些主机可以接受cookie,如果不指定,则默认当前文档的主机(不包含子域名),如果指定了Domain,则一般包含子域名。
Path标识指定主机下哪些路径可以接受到cookie,子路径也会被匹配 - js
js可以通过
document.cookie访问和设置非httponly标记的cookie - httponly 设置了HttpOnly标识的cookie不能被js调用,设置httponly可以有效防范XSS攻击
- Secure 标记为Secure的cookie只能通过被Https协议加密过的请求发送给服务端
- Session
保存用户信息的时候,cookie一般配合session使用,cookie保存一个sessionid,用户信息则保存到redis中,具体过程如下:
- 用户进行登录,用户提交的账号密码放在请求报文中发送给服务端
- 服务端进行验证,如果正确就把用户信息存储到redis中,他在redis中的key称之为sessionid
- 服务器返回响应报文中set-cookie字段包含这个sessionid,客户端把该cookie值存储到浏览器。
- 客户端对同一服务器发送请求,服务端接受请求,取出sessionid,从redis提出用户信息进行操作。
- 浏览器禁用cookie 此时只能用session,只能将sessionid作为url参数进行传递。
缓存
- 缓存用于降低客户端获取资源的延迟,当客户端请求的资源一样时,使用缓存能使读取资源速度更快。主要的实现方法是让代理服务器进行缓存或者让客户端浏览器进行缓存。
- HTTP缓存的运作方式主要分为以下几步:
- 客户端请求资源,查看自己是否有缓存,如果没有则向服务器索取,如果有,到第二步
- 检查缓存新鲜度,查看缓存是否过期,如果没有过期,则直接使用,无需向服务端发送请求,如果过期,到第三步
- 向服务器发送请求,验证是否过期,如果没有过期,则可以继续使用,如果过期了,则向服务器请求资源。
强缓存
不需要发送请求到服务器,直接读取浏览器缓存。状态码为200。强缓存又分为disk cache和memory cache,存储的位置由浏览器决定。强缓存有Expires, Cache-Control, Pragma三个属性共同控制
- Expires
Expires的值是一个HTTP日期,当系统时间超过了这个日期,则缓存失效,由于系统时间和服务器时间可能不同,所以Expires来控制并不稳定,所以其优先级最低。 - Cache-Control
Cache-Control是HTTP/1.1新增的属性,在请求头和响应头都可以使用,主要有以下几个属性。
1. max-age: 单位是秒,是距离发起请求经过的时间,超过这个时间缓存就失效。
2. no-cache: 不使用强缓存,即需要判断缓存是否新鲜
3. no-store: 不使用缓存(包括协商缓存)
4. private: 专用于个人的缓存,不能被中间代理,CDN等缓存
5. public: 响应可以由中间代理、CDN等缓存
6. must-revalidate: 缓存过期前可以使用,过期后必须向服务器进行验证 - Pragma
只有一个属性,作用和Cache-Control里的no-cache相同
协商缓存
当浏览器的强缓存失效或者设置了不走强缓存,并且请求头中设置了If-Modified-Since或者If-None-Match时,就会将这两个属性拿到服务端验证是否命中协商缓存,如果命中,就会加载浏览器缓存,返回304,并且响应头会设置ETag或Last-Modify属性、
- Etag/If-None-Match的值是一串hash码,当服务端的文件发生改变,hash值就会改变,通过请求头的If-None-Match的值和文件的hash值进行比较,如果没有改变,说明缓存仍为新鲜,没有过期,则命中协商缓存,返回304。如果不一样,则需请求服务端资源。ETag有强弱校验之分,hash码是W开头的为弱校验。
- Last-Modified/ If-Modified-Since Last-Modified/ If-Modified-Since代表文件的最后修改时间,第一次请求服务端会把资源最后修改时间放到Last—Modified响应头中,第二次发起请求就会携带这个修改时间放到If-Modified-Since请求头中进行对比,如果相同,则命中协商缓存,返回304。
HTTPS
HTTPS并不是新协议,而是让HTTP和SSL/TLS进行通信,然后再由SSL/TLS和TCP进行通信,基于此,HTTPS具有了加密、认证和完整性保护。
加密
- 对称加密
对称密钥加密,即加密和解密使用同一密钥,缺点是无法将密钥安全的传输给通信方 - 非对称加密
公钥谁都可以获得,通信发送方获得公钥后对数据进行加密,接收方收到内容后用私钥进行解密。注意,用公钥加密后的数据反而无法用公钥进行解密,这就是为什么是非对称加密
证书
证书由CA签发,通过使用证书对通信方进行认证,服务器的运营人员向CA提出公开密钥的申请,CA在判明提出申请者的身份后,会对已申请的公钥做数字签名,然后分配这个已签名的公钥,并将公钥与证书绑定在一起。
进行HTTPS通信时,服务器会把证书发送给客户端,客户端取得公钥后会先使用数字签名进行验证,如果验证通过,就可以开始通信。
HTTPS的加密过程
- 客户端和服务端进行通信,客户端发送TLS版本、加密套件、第1个随机数给服务端
- 服务端确认支持的TLS版本、加密套件,并生成第2个随机数发送给服务端
- 服务端还发送了证书(里面有公钥)给客户端
- 客户端接收公钥,并生成第三个随机数,也就是预主密钥,然后用公钥对预主密钥进行加密,发送给服务端
- 服务端接收加密后的预主密钥,用私钥进行解密,所以服务端就拥有了预主密钥
- 服务端和客户端都用第一随机数和第二随机数和预主密钥进行计算,得到会话密钥,非对称加密结束
- 客户端和服务端用会话密钥进行对称加密通信。
HTTP/1.1 HTTP2 HTTP3
HTTP/1.1
- HTTP/1.1开始,默认是长连接,即建立一次TCP连接可以进行多次HTTP连接,而这些HTTP连接间,必须等待前一个HTTP请求响应后,才能发送HTTP请求。
- 对于浏览器来说,我们打开一个网页,首先建立TCP连接,然后浏览器向服务端请求HTML文件,收到HTML文件后,根据HTML文件再请求css、js等文件。而如果请求队伍里有一个文件没有接收到,那么后面的文件也没法接收,这就会造成HTTP队头阻塞。由于单个持久连接效率比较低,所以不同浏览器之间有不同的持久连接数。
- HTTP/1.1里还有一个叫管线化的技术,即单个连接一次性可以发送多个请求,但必须按发送的顺序接收,也就是说如果第一个响应报文丢失,第二个就会变成第一个,由于这种不确定性,一般不使用。
- 在开发层面,有很多减少请求防止丢失和队头阻塞的操作,比如雪碧图、或base64编码。
- HTTP首部默认是没有压缩的,而且请求头和响应头内有相当多字段重复,这使得HTTP/1.1报文十分臃肿。
HTTP/2
- 为了解决HTTP/1.1队头阻塞的问题,HTTP/2引入了多路复用。在HTTP/2中,报文被分为首部帧和数据帧,分别对应了原本报文的首部和实体。通过多路复用,单个TCP连接就可以进行交错发送请求和响应,而且请求和响应之间互不影响。
- 多路复用的实现关键在于HTTP/2内的流标识符,流标识符可以使得请求和响应按照顺序进行组合,所以HTTP/2内不需要按顺序接收。而且帧类型里还可以设置优先级,标记权重。
- HTTP/2还对首部进行了压缩,即要求浏览器和服务器都保存一张静态可读表,根据值得到value进行保存。而由于是重复的首部,可以实现在二次请求和响应里直接去掉,另外cookie这样的可以作为动态信息存放在动态表里。
- HTTP/2还有一个特性为服务端推送,即浏览器进行请求html文件,服务器提前把后续可能要的文件如css文件,js文件返回给浏览器,实际上这种请求会导致用户的缓存大大增加,而且容易遭受DDOS攻击。
- 然而HTTP/2只解决了应用层的阻塞,然而HTTP基于TCP,运输层的TCP连接如果有报文丢失,仍会造成TCP队头阻塞。
HTTP/3
- HTTP3将TLS和TCP整合在一起,减少了传输时间,而且恢复的会话还可以进行缓存,实现0RTT,但是HTTP/3是基于UDP的,基于UDP建立了新的协议QUIC,这个QUIC实际上就是TCP和TLS的整合
- 解决TCP队头阻塞依赖于QUIC帧,QUIC帧内还有ConnectionID连接id,没搞懂,后面填坑。
GET POST区别
- 作用:GET用于检索和获取,POST用于传输
- 参数:GET请求的参数出现在URL中,POST的参数出现在实体主体中,由于URL长度的限制,GET的参数会受到限制。由于URL只支持百分号编码,因此如果URL有中文等字符需要先进行编码,POST的参数支持标准字符集。
- 安全:安全的HTTP请求不会改变服务器状态,也就是说是只读的,所以GET是安全的而POST是不安全的。 可以引出幂等的概念,幂等的HTTP方法,同样的请求执行一次或多次,效果是一样的,服务器状态也是一样的,也就是说幂等方法不具有副作用,GET方法就是幂等的,POST是非幂等的。