前言
这段时间总结的计网八股,有待补充
一、TCP/IP网络模型有几层
1.1 应用层
应用层只需要专注于为用户提供功能,比如HTTP、FTP、SMTP、SFTP等,应用层是工作在操作系统中的用户态,传输层及以下工作在内核态。
1.2 传输层
应用层的数据包会传给传输层,传输层
是为应用提供网络支持的。
传输层有两个传输协议,分别是TCP和UDP
TCP的全称是传输控制协议,HTTP应用层使用的就是TCP协议,TCP比UDP多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。
应用需要传输的数据可能会非常大,因此当传输层的数据包大小超过MSS(TCP最大报文长度),就要将数据包分块,即使在传输过程中丢失或损坏了一个分块,也只需重写发送该分块,而不用重写发送整个数据包,每个分块称为一个TCP段
,标识起点和终点
1.3 网络层
网络层负责将数据从一个设备传输到另一个设备
网络层最常使用的是IP协议,IP协议会将传输层的报文作为数据部分,再加上IP包头组成IP报文,如果IP报文大小超过MTU(以太网一般为1500B),就会再次进行分片
,得到一个即将发送到网络的IP报文。一般用IP地址给设备进行编号,将IP地址分为两个部分:
- 一个是
网络号
,负责标识该IP地址是属于哪个子网的 - 一个是
主机号
,负责标识同一子网
下的不同主机
路由器会根据IP地址的网络号进行转发,IP协议的的寻址作用告诉我们去往下一个目的地该往哪个方向走,路由则根据下一个目的地选择路径。寻址更像再导航,路由更像在操作方向盘
1.4网络接口层
生成了IP头部之后,网络接口层
在IP头部的前面加上MAC头部,并封装成数据帧(Data frame)发送到网络上。
以太网是一种在局域网
内,把附近的设备连接器里,使他们之间进行通讯的技术。以太网在判断网络包目的地和IP的方式不同,因此必须采用相匹配的方式才能在以太网中将包发往目的地,在以太网进行通讯要用到MAC地址。MAC头部是以太网使用的头部,它包含了接收方ARP协议获取
和发送方的MAC地址等信息。
二、键入网址到网页显示,期间发生了什么?
HTTP
浏览器做的第一步工作就是对URL
进行解析,从而生成发送给web
服务器的请求信息。对URL
进行解析之后,浏览器确定了web服务器和文件名,接下来就是根据这些信息来生成HTTP请求消息。
DNS真实地址查询
通过浏览器解析URL并生成HTTP消息,需要委托操作系统把消息发送给web
服务器,在发送之前,需要查询服务器域名对应的IP地址
,有一种服务器专门保存了web
服务器域名和IP
的对应关系,它就是DNS
服务器
域名的层级关系:越靠右
的位置表示其层级越高
,DNS是树状结构,当客户端需要域名解析时,会先向本地域名服务器请求,如果缓存中没有,则会去问它的根域名服务器->顶级域名服务器->权威域名服务器,只指路不带路
。
指南好帮手-协议栈
通过DNS获取到IP后,可以把HTTP的传输工作交给操作系统中的协议栈
浏览器通过调用Socket库,来委托协议栈工作,协议栈的上半部分有两块,分别是负责收发数据的TCP和UDP协议,这两个传输协议会接受应用层的委托执行收发数据的操作。
协议栈的下面一半是用IP协议控制网络包收发操作,在互联网上传数据时,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由IP负责的。
IP中还包含ICMP
和ARP
协议。
ICMP
用于告知网络包传送过程中产生的错误以及各种控制信息ARP
用于根据IP地址查询到相应的以太网MAC地址
IP下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡负责完成实际的收发操作,也就是对网络的信号执行发送和接收操作。
可靠传输TCP
TCP有源端口号
和目标端口号
接下来是包的序号
(表示这一次发送数据过去的第一个字节大小)
确认号
(表示希望下一次对方给我送过来的数据从确认号标记的字节开始)
状态位
(SYN:发起一个连接;ACK:回复;RST:重新连接;FIN:结束连接)
窗口大小
:TCP做流量控制
,通信双方各声明一个窗口(缓存大小),标识自己当前能够的处理能力。
拥塞控制
:网络环境不好时,控制发送的速度。
TCP三次握手
- 一开始,客户端和服务端都处于
closed
状态,先是服务端主动监听某个端口。处于listen状态。 - 然后,客户端主动发起连接
SYN
,之后处于SYN-SENT
状态 - 服务端收到发起的连接,返回
SYN
,并ACK
客户端的SYN
,之后处于SYN-RCVD
状态。 - 客户端收到服务端发送的
SYN
和ACK
之后,发送对SYN
确认的ACK
,之后处于ESTABLISHED
状态,因为它一发一收成功了 - 服务端收到
ACK
的ACK
后,处于ESTABLISHED
状态
三次握手的目的是保证双方都有发送和接收的能力
MTU:
一个网络包的最长长度,以太网中一般为1500字节
MSS
:除去IP和TCP头部后,一个网络包所能容纳的TCP数据的最大长度
远程定位-IP
TCP模块在执行连接、收发、断开等各阶段操作时,都需要委托IP模块将数据封装成网络包
发送给通信对象
在IP协议里面有源IP地址
和目标地址IP
:
- 源地址IP:即是客户端输出的IP地址
- 目标地址:即通过DNS域名解析得到的web服务器IP
当存在多个网卡时,填写源地址IP。就需要判断到底该填写哪个地址,即判断在多块网卡中判断应该使用哪一个网卡来发送包。
根据路由表
规则,判断哪一个网卡作为源地址IP,依次将目标IP地址与网卡中每个条目的子网掩码做位与运算,再与destination作比较,不一致匹配失败,否则匹配成功。最后一个条目一定匹配,因为destination 和 子网掩码都是0.0.0.0,即是默认网关
加上了ip地址之后,数据包知道目的地的位置,但下一站该去哪还不清晰。
两点传输 MAC
在MAC包头里需要发送方MAC地址
和接收方MAC地址
,用于两点之间的传输
查看路由表,可用知道要发送的位置的IP地址,因此只需将IP地址广播出去通过ARP协议
,然后会有机器回答,这个IP地址是我的,MAC地址是…
(会有ARP缓存,只有缓存不命中时,才会发送ARP广播查询)
出口-网卡
网络包存放在内存中的一串二进制数字信息,因此没有办法直接传送给对方,需要将数字信息转换为电信号
,网卡驱动获取数据包后,会将其复制
到网卡内的缓存区中,接着会在其`开头加上报头和起始帧分界符(标记包起始位置),在末尾加上用于校验错误的帧校验序列(检查包传输过程是否有损坏)
送别者-交换机
交换机工作在MAC层,也称为二级网络设备
交换机本身没有MAC地址,只维护了一张MAC地址表,包含两个信息:
- 一个是设备的MAC地址
- 一个是该设备连接在交换机的哪个端口上
交换机根据MAC地址表查询MAC地址,然后将信号发送到相应的端口
,如果MAC地址表中找不到指定的MAC地址,在这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,相应的接收者接收到包,而其他设备则会忽略这个包,目标设备返回了响应包后,交换机可以将它的地址写入MAC地址表,下次就可以直接传到相应的端口
出境大门-路由器
路由器
是基于IP设计的,俗称三层
网络设备,路由器的各个端口都具有MAC地址和IP地址交换机
是基于以太网设计的俗称二层
网络设备,交换机的端口不具有MAC地址
路由器端口会接收发给自己的以太网包,然后路由表
查询转发目标,再有相应的端口作为发送方将以太网发送出去。
路由器先进行错误校验(FCS校验),没问题则检查MAC头部中的接收方MAC地址
,如果是就放到接收缓冲区,否则丢弃这个包。
路由器会去掉
包的MAC头部,当包到达路由器后,MAC头部会被舍弃
,之后会根据IP头部的内容进行包的转发工作,查询路由表判断转发目标,路由表会去掉MAC头部,加上新的MAC头部,直至包传到目标IP
三、HTTP
3.1常见面试题
3.1.1 HTTP常见字段有哪些
Host:www.A.com 指定服务器的域名
content-length:1000 代表本次回应的数据长度为1000字节
connection:keep-alive 长连接
content-type:text/html;charset=utf-8:用于服务器
回应时,告诉客户端,本次数据是什么格式
accept:*/*用于客户端请求时,用accept声明自己可以接收哪些数据格式
content-encoding:gzip:说明数据的压缩方法,表示服务器返回的数据用了什么压缩格式
3.1.2 Get与POST
根据RFC规范,GET的语义是从服务器获取指定的资源
,`POST的语义是根据请求负荷(报文body)对指定的资源做出处理
GET和POST方法都是安全和幂等的吗
安全:请求方法不会破坏服务器上的资源
幂等:多次执行相同的操作,结果都是相同
GET方法就是安全且幂等,可以对GET请求的数据做缓存,这个缓存可以做到浏览器本身上,也可以做到代理商,而且在浏览器中GET请求可以保存为书签
POST是新增或提交数据的操作,会修改服务器上的资源,是不安全的,且多次提交数据会创建多个资源,所以是不幂等的
3.1.3 HTTP缓存有哪些实现方式
即将HTTP请求响应的数据都缓存在本地
,下次就可以直接读取本地的数据,不必通过网络获取服务器的响应(缓存技术),两种实现方式:强制缓存和协商缓存
强制缓存
使用cache-control来实现强缓存,具体流程如下:
- 当浏览器第一次请求访问服务器资源时,服务器返回这个资源的同时,在response头部加上cache-control,cache-control中设置了过期时间大小。
- 浏览器再次请求访问服务器中的该资源时,会先
通过请求该资源的时间与cache-control中设置的过期时间大小比较,来计算是否过期
,未过期,则使用缓存,否则重新请求服务器 - 服务器再次收到请求时,会再次更新response头部的cache-control
3.1.4 HTTP 1.1的优缺点
优点
- 简单,基本报文格式是
header + body
,头部信息也是key-value
简单文本的形式,易于理解
- 灵活和易于扩展
- 应用广泛和跨平台
缺点 - 无状态双刃剑。无状态一方面可以减轻服务器的负担,把更多的CPU和内存用来对外提供服务;另一方面,服务器没有记忆能力,完成有关联性的操作时会非常麻烦
- 明文传输,不安全。
HTTP1.1的性能如何
- 长连接
保持TCP的连接,即在一次TCP连接,传输多个数据包,减少TCP连接重复建立和断开造成的额外开销。 - 管道网络传输
在同一个TCP连接里,客户端可以发起多个请求,只要第一个请求发出去了,就不必等其回来,可以发第二个请求出去,减少整体的响应时间
服务器必须按照接收请求的顺序发送对这些管道化请求的响应,因此,HTTP1.1管道解决了请求的队头阻塞,但是没有解决响应的队头阻塞
3.1.5 HTTP到HTTPS
HTTPS在HTTP与TCP层之间加入了SSL/TLS
协议,可以很好的解决上述风险:
信息加密
:交互信息无法被窃取校验机制
:无法篡改通信内容身份证书
HTTPS如何解决上述三个风险·:
混合加密
的方式实现信息的机密性
摘要算法
的方式实现完整性- 将服务器公钥放入
数字证书
中,解决冒充的风险
HTTPS三种方式
混合加密
利用混合加密
的方式来保证信息的机密性
,解决了窃听的风险,对称加密+非对称加密
- 通信建立前采用
非对称加密
的方式交换会话密钥,后续就不再使用非对称加密 - 通信过程中全部使用
对称加密
的会话密钥来加密明文数据
原因在于
对称加密
只使用一个密钥,运算速度快,密钥必须保密,无法做到安全的密钥交换。非对称加密
使用两个密钥:公钥和私钥,公钥可以任意分发而私钥保密,解决了密钥交换问题但速度慢
摘要算法 + 数字签名
用摘要算法(哈希函数)来计算内容的哈希值
,这个哈希值是唯一的,且无法通过哈希值推导出内容
通过哈希算法可以确保内容不被更改,但是不能保证内容 + 哈希值 不会被
数字证书
3.1.6 HTTP的演变
HTTP1.0 -> HTTP1.1
改进:
- 使用长连接的方式改善了HTTP1.0短链接造成的性能开销
- 支持管道网络传输,不会出现HTTP请求阻塞,但仍会出现HTTP响应阻塞
性能瓶颈: - 请求响应头部未经压缩就发送,冗长的首部造成的浪费较多。
- 如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞
- 请求没有优先级
- 请求只能从客户端开始,服务端只能被动响应
HTTP1.1 -> HTTP2
HTTP2协议是基于HTTPS的
- 头部压缩(压缩头,如果同时发出多个请求,他们的头是一样的或是相似的,协议会帮助
消除重复的部分
- 二进制格式(全面采用
二进制格式
,头信息和数据体都是二进制,并统称为帧:头信息帧和数据帧
,收到报文后,机器无需将明文的报文转化成二进制,而是直接解析成二进制报文,增加数据传输的效率
- 并发传输(
针对不同的HTTP请求用独一无二的Stream ID来区分,接收端可以通过Stream ID有序组装成HTTP消息,不同Stream的帧是可以乱序发送的,因此可以并发不同的Stream
- 服务器主动推送资源(服务端主动向客户端发送消息)
缺点:仍会出现对头阻塞问题,在TCP层面出现的,如果中间丢失一个TCP包,所有HTTP请求必须等待这个丢了的包重传回来
HTTP2.0 -> HTTP3.0
HTTP3把HTTP下层的TCP协议改成了UDP
QUIC有以下三个特点
- 无对头阻塞:
当某个流发生丢包时,只会阻塞这个流,其他流不会受到影响,因此不存在队头阻塞问题
- 更快的连接建立
- 连接迁移
3.2 HTTP1.1如何优化
如何避免发送HTTP请求
对于重复性的HTTP请求,会将请求-响应的数据缓存在本地
,即使用了缓存技术
如何减少HTTP请求次数
三个方面:
- 减少重定向请求次数
- 合并请求
- 延迟发送请求
对于第一个方面,将重定向的工作交给代理服务器完成,就可以减少HTTP请求次数了
对于第二个方面,和并请求,即将多个访问小文件的请求合并成一个大的请求,减少请求,也减少了重复发送的HTTP头部
对于第三个方面,延迟发送请求,一般HTML里会包含很多HTTP的URL,当前不需要的资源,我们没必要进行获取,于是可以通过按需获取
的方式,来减少第一时间的HTTP请求次数
HTTPS是应用层协议,需要先完成TCP连接建立,然后走TLS握手过程后,才能建立通信安全的连接
3.2 HTTPS加解密流程
HTTPS工作流程:
- 用户在浏览器发起HTTP请求,默认使用服务端的443端口进行连接
HTTPS需要使用一套CA数字证书
,证书内会附带一个公钥Pub
,而与之对应的私钥private
保留在服务端不公开 - 服务端收到请求,返回配置好的包含
公钥pub
的证书给客户端 - 客户端收到
证书
,校验合法性,主要包括是否在有效期内、证书的域名与请求的域名是否匹配,上一级证书是否有效,如果不通过,显示HTTPS警告信息,如果通过则继续 - 客户端生成一个用于对称加密的
随机key
,并用证书内的公钥pub
进行加密,发送给服务端 - 服务端收到
随机key
的密文,使用与公钥pub
配对的私钥private
进行解密,得到客户端真正想发送的随机key
- 服务端使用客户端发来的
随机key
对要传输的HTTP数据进行对称加密,将密文返回给客户端 - 客户端使用
随机key
对称解密密文,得到HTTP数据明文 - 后续HTTPS请求使用之前交换好的
随机key
进行对称加解密
考虑中间人攻击
的情况,非对称加密的算法都是公开
的,所有人都可以自己生成一对公钥私钥。因此如果中间人将服务器的公钥替换成自己的公钥,就出现中间人攻击的情况,能够获取客户端和服务器相传递的明文数据。
出现这一问题的核心原因是客户端无法确认收到的公钥是不是真的是服务器发来的
,为了解决这一问题,互联网引入了CA证书。
私钥除了解密的功能外,还可以进行数字签名
,一种防伪技术,只要有人篡改了证书,那么数字签名必然失败。具体过程如下:
- CA机构拥有自己的一对公钥和私钥
- CA机构在颁发证书时对证书明文信息进行哈希
- 将哈希值用私钥进行
加签
,得到数字签名
明文数据和数字签名组成证书,传递给客户端
- 客户端得到证书,分解成明文部分和数字签名sig1
- 用CA机构的公钥进行
解签
,得到sig2 - 用证书里声明的哈希算法对明文text部分进行哈希得到H
- 当自己计算得到的哈希值H与
解签
后的sig2相等
,表示证书可信,没有被篡改
3.9为什么要有websocket(既然有HTTP协议)
- TCP协议本身是
全双工
的,但我们最常用的HTTP1.1,虽然基于TCP协议,但它是半双工
的,对于大部分需要服务器主动推送到客户端的场景不太友好,因此我们需要使用支持全双工的websocket协议 - HTTP1.1里,只要客户端不问,服务端就不答,因此对于登陆页面这样的简单场景,可以使用
定时轮询或者长轮询
的方式来实现服务端推送
的效果。 - 因为各个浏览器都支持HTTP协议,所以WebSocket会先利用HTTP协议加上一些特殊的header头进行握手升级操作,升级后跟HTTP没有任何关系了,之后用WebSocket的数据格式进行收发数据。
怎么建立webSocket连接
浏览器在TCP三次握手
建立连接之后,都统一使用HTTP协议
先进行一次通信
- 如果此时是
普通的HTTP请求
,那么后续双方还是继续用HTTP协议进行交互 - 如果这时候是想建立
webSocket连接
,就会在HTTP请求头里带上一些特殊的header头
(此时返回的码是101,即协议切换
)、
番外
sso单点登录
单点登录就是在多个系统中,用户只需要一次登录,各个系统即可感知该用户已经登录
回顾单系统登录
HTTP是无状态
的协议,意味着服务器无法确认用户的信息
,于是给每一个用户都发一个通行证,即cookie
,同时服务器上建立了一份客户明细表session
,session根据cookie来识别是否是同一个用户
因此但系统登录的流程是
登录
:将用户信息保存在session对象中- 如果在session对象中能查到,说明已经登录
- 如果在session对象中查不到,说明未登录
注销
:从session中删除用户的信息记住我,即关掉浏览器后,重新打开浏览器仍能保持登录状态
:配合cookie来用
该处使用的url网络请求的数据。
多系统登录的问题与解决
session不共享问题
多系统和单系统不一样,多系统会有多个web服务器,即可能会有多个tomcat,而session是依赖当前系统的tomcat,所以系统A的session和系统B的session是不共享的。
解决系统之间session不共享问题有以下几种方案:
- tomcat集群session全局复制(集群内每个tomcat的session完全同步)
会影响性能,不建议
- 根据请求的IP进行
Hash映射
到对应的机器上(这会造成请求的IP会一直访问同一个服务器,如果服务器宕机,会丢失了一大部分session数据) - 把session数据放在redis中(
建议
)
即其实主要两个变化: 将登录功能抽取为一个系统(SSO),其他系统请求SSO登录
本来将用户信息存到session,现在将用户信息存到redis
cookie跨域的问题
cookie是不能跨域的
,因为浏览器只会带一个域名服务器发给它的cookie去访问该域名服务器,不会在访问其它服务器时带上别的服务器给它的cookie。
针对cookie存在的跨域问题,有几种解决方案:
- 服务端将cookie写到客户端后,客户端对cookie进行解析,将token解析出来,此后请求都把这个token带上。
- 多个域名共享cookie,在写到客户端的时候设置cookie的domain
- 将token保存在sessionStorage(不依赖cookie就没有跨域的问题)
2.2.3 CAS原理
CAS(central authentication service),将登录单独抽取成系统出来
,即现在有两个系统系统Awww.java3y.com
和系统Bwww.java4y.com
和 一个SSO www.sso.com
如若请求了系统A,由于未登录,会重定向到sso认证中心,并将自己的地址作为参数
,sso认证中心发现用户未登录,将用户引导至登录页面,用户输入用户名和密码进行登录,用户与认证中心建立全局会话(生成一份token,写入cookie中,保存在浏览器上)
随后认证中心带上生成的token,访问系统A,系统A收到后再去认证中心验证这个token是否正确,如果正确,则系统A和用户建立局部会话(创建session
),至此用户和系统A都已是登录状态。
此时,用户访问系统B,带上cookie,重定向到sso认证中心,认证中心根据带过来的cookie
发现已经与用户建立全局会话,认证中心
总结
这段时间总结的计网八股,后面有待补充