文章目录
- 一 基本概念
- 1 计算机网络体系结构
- 2 时延
- 二 应用层:HTTP
- 1 请求和响应报文、常见 header
- 2 URL & RESTful API
- 3 HTTP 协议通信过程
- 4 HTTP 方法
- 5 HTTP 状态码
- 6 短连接、长连接与流水线
- 7 Cookie
- 8 Session
- 三 应用层:HTTPS
- 1 加密方式
- 2 证书认证
- 四 应用层:其它协议
- 1 DNS
- 2 FTP
- 3 SMTP、POP3、IMAP
- 4 DHCP
- 五 传输层:TCP & UDP
- 1 TCP vs UDP
- 2 三次握手
- 3 四次挥手
- 4 TCP 如何实现可靠传输
- 5 滑动窗口协议
- 6 TCP 流量控制
- 7 TCP 拥塞控制
- 六 常见问题
- 1 从输入 URL 地址到显示主页的过程
- 2 HTTP:GET 和 POST 的区别
一 基本概念
1 计算机网络体系结构
数据在各层之间的传递过程:在向下的过程中,需要添加下层协议所需要的首部或者尾部,而在向上的过程中不断拆开首部和尾部
- 五层协议
名称 | 作用 |
---|---|
应用层 | 为特定应用程序提供数据传输服务,例如 HTTP、DNS 等协议,数据单位为报文 |
传输层 | 为进程提供通用数据传输服务,包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为 报文段 (主要提供完整性服务);用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为 用户数据报(主要提供及时性服务 ) |
网络层 | 为主机提供数据传输服务,把传输层传递下来的报文段或者用户数据报封装成分组 |
数据链路层 | 为同一链路的主机提供数据传输服务,把网络层传下来的分组封装成帧 |
物理层 | 在传输媒体上传输数据比特流 |
2.OSI七层协议
- 应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
- 表示层 :数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题
- 会话层 :建立及管理会话
- 五层协议没有表示层和会话层,而是将这些功能留给应用程序开发者处理
3.TCP/IP 协议
- 应用层、传输层、网际层、网络接口层
- 相当于五层协议中数据链路层和物理层合并为网络接口层
- 不严格遵循 OSI 分层概念,应用层可能会直接使用 IP 层或者网络接口层
2 时延
总时延 = 排队时延 + 处理时延 + 传输时延 + 传播时延
- 排队时延:分组在路由器的输入队列和输出队列中排队等待的时间,取决于网络当前的通信量
- 处理时延:主机或路由器收到分组时进行处理所需要的时间,例如分析首部、从分组中提取数据、进行差错检验或查找适当的路由等
- 传输时延:主机或路由器传输数据帧所需要的时间
- 传播时延:电磁波在信道中传播所需要花费的时间,电磁波传播的速度接近光速
二 应用层:HTTP
1 请求和响应报文、常见 header
- 客户端发送一个请求报文给服务器,服务器根据请求报文中的信息进行处理,并将处理结果放入响应报文中返回给客户端
- 请求报文
- 请求行:包含请求方法、URL、协议版本
- 请求 Header:多个以冒号分隔的键值对
- 分隔行
- 请求体
GET http://www.example.com/ HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Host: www.example.com
If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT
If-None-Match: "3147526947+gzip"
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 xxxparam1=1¶m2=2
- 响应报文
- 响应行:包含协议版本、状态码以及描述
- 响应 Header:多个以冒号分隔的键值对
- 分隔行
- 响应体
HTTP/1.1 200 OK
Age: 529651
Cache-Control: max-age=604800
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 648
Content-Type: text/html; charset=UTF-8
Date: Mon, 02 Nov 2020 17:53:39 GMT
Etag: "3147526947+ident+gzip"
Expires: Mon, 09 Nov 2020 17:53:39 GMT
Keep-Alive: timeout=4
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Proxy-Connection: keep-alive
Server: ECS (sjc/16DF)
Vary: Accept-Encoding
X-Cache: HIT<!doctype html>
<html>
<head><title>Example Domain</title>// 省略...
</body>
</html>
Request header
- 【Accept】 浏览器可接收的数据格式
- 【Accept-Encoding】 浏览器可接收的压缩算法,如 gzip
- 【Accept-Language】 浏览器可接收的语言,如 zh-CN
- 【Connection】 keep-alive 持久性连接,close 非持久性连接
- 【cookie】
- 【Host】 请求的域名
- 【User-Agent】浏览器信息
- 【Content-Type】 发送数据的格式(POST),如 application/json
Response header
- 【Content-Type】 返回数据的格式,如 application/json
- 【Content-length】 返回数据的字节数
- 【Content-Encoding】 返回数据的压缩算法,如 gzip
- 【Set-Cookie】服务器给客户端的 cookie
更多查看
2 URL & RESTful API
URI/URL
- URI(Uniform Resource Identifier,统一资源标识符)是抽象的标识资源的方式,它的具体实现包括 URL( Uniform Resource Locator,统一资源定位符) 和 URN (Uniform Resource Name,统一资源名称)
- 以上并不代表 URI = URL + URN,而是代表 URL 是 URI,URN 也是 URI
- HTTP 使用 URL 来定位资源
RESTful
- RESTful 架构可以充分的利用 HTTP 协议的各种功能,是 HTTP 协议的最佳实践
- 把 HTTP 方法作为动词,URL 作为名词(视为资源),作为一次请求
- 客户端请求时,要明确告诉服务器,接受 JSON 格式,请求的 HTTP 头的
ACCEPT
属性要设成application/json
- 服务端返回的数据应该是一个 JSON 对象,服务器回应的 HTTP 头的
Content-Type
属性要设为application/json
3 HTTP 协议通信过程
HTTP 是应用层协议,它以 TCP(传输层)作为底层协议,默认端口为 80
- 服务器在 80 端口等待客户的请求
- 浏览器发起到服务器的 TCP 连接(创建套接字 Socket)
- 服务器接收来自浏览器的 TCP 连接
- 浏览器(HTTP 客户端)与 Web 服务器(HTTP 服务器)交换 HTTP 消息
- 关闭 TCP 连接
4 HTTP 方法
- 安全的 HTTP 方法不会改变服务器的状态。从这个角度出发,GET、HEAD、OPTIONS 是安全的,而 POST、DELETE‘PUT 是不安全的
- 幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的(幂等方法不应该具有副作用)。从这个角度出发,GET,HEAD,PUT 和 DELETE 等方法都是幂等的,而 POST 方法不是
- GET
获取资源 - HEAD
获取报文首部,和GET
方法类似,但是不返回报文实体主体部分
主要用于确认 URL 的有效性以及资源更新的日期时间等 - POST
传输实体主体 - PUT
上传文件
没有验证机制,存在安全性问题,一般不使用 - PATCH
对资源进行部分修改
PUT
也可以用于修改资源,但是只能完全替代原始资源,PATCH
允许部分修改 - DELETE
与PUT
功能相反,并且同样不带验证机制 - OPTIONS
查询指定的 URL 能够支持的 HTTP 方法 - CONNECT
要求在与代理服务器通信时建立隧道
使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输
- TRACE
追踪路径,服务器会将通信路径返回给客户端
发送请求时,在Max-Forwards
首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输
5 HTTP 状态码
- 服务器返回的 响应报文 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果
- 常见状态码
状态码 | 含义 |
---|---|
200 | 成功 |
301 | 永久重定向(浏览器自动处理,每次直接访问新地址) |
302 | 临时重定向(浏览器自动处理,每次先访问老地址,再重定位到新地址) |
304 | 资源未修改 |
403 | 没有权限 |
404 | 资源未找到 |
500 | 服务器错误 |
504 | 网关超时 |
6 短连接、长连接与流水线
- 短连接每进行一次 HTTP 通信就要新建一个 TCP 连接,长连接只需要建立一次 TCP 连接就能进行多次 HTTP 通信
- 在 HTTP/1.1 之前默认短连接,HTTP/1.1 及之后开始默认长连接
- 默认情况下,HTTP 请求是按顺序发出的,下一个请求只有在当前请求收到响应之后才会被发出。流水线是在 同一条长连接上连续发出请求,而不用等待响应返回,这样可以减少延迟
7 Cookie
- HTTP 是无状态的协议,HTTP/1.1 引入 Cookie 来保存状态信息
- Cookie 由服务器发送到用户浏览器,并存放在客户端,在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器
- 创建过程:
# 服务器发送的响应报文包含 Set-Cookie 首部字段
# 客户端得到响应报文后把 Cookie 内容保存到浏览器中
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry[page content]
# 客户端之后对同一个服务器发送请求时会从浏览器中取出 Cookie 信息
# 通过 Cookie 请求首部字段发送给服务器
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
8 Session
除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全
- 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
- 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
- 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
- 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作
Cookie 被禁用怎么办?
最常用的就是利用 URL 重写把 Session ID 直接附加在 URL 路径的后面
三 应用层:HTTPS
- 默认端口号是 443
- HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信,也就是说 SSL 作用于 HTTP 和 TCP 之间
- 通过使用 SSL,HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)
1 加密方式
-
对称密钥:加密和解密使用同一密钥
-
非对称密钥:公开密钥所有人都可以获得,通信发送方获得 接收方的公开密钥 之后,就可以使用公开密钥进行加密,接收方收到通信内容后使用私有密钥解密
-
HTTPS 采用混合加密机制:
使用 非对称密钥 加密方式,传输 对称密钥 加密方式所需要的 Secret Key,从而保证安全性;
获取到 Secret Key 后,再使用 对称密钥加密方式进行通信 ,从而保证效率
2 证书认证
根本目的是传递服务器的公钥
- 数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构
- CA 知道服务器的公钥,向服务器颁发证书,并附上 CA 私钥对消息摘要的加密签名
- 服务器获得 CA 办法的证书,并将证书传递给客户端
- 客户端获得证书,并且客户端知道 CA 公钥,使用 CA 公钥对证书上的签名解密,同时对消息进行散列处理得到摘要
- 比较摘要,验证证书的真实性。如果客户端验证服务器的证书是真实的,则信任服务器的公钥
四 应用层:其它协议
1 DNS
- DNS 是一个分布式数据库,提供了主机名和 IP 地址之间 相互转换 的服务
- 域名具有层次结构,从上到下依次为:根域名、顶级域名、二级(权威)域名
- DNS 可以使用 UDP 或者 TCP 进行传输,使用的端口号都为 53
- 一般使用 UDP 进行传输,除非返回的响应超过的 512 字节(UDP 最大只支持 512 字节的数据)
- 查询可以通过两种方式:递归查询和迭代查询
2 FTP
- 使用两个 TCP 连接进行文件传输,分别是数据连接和控制连接
- 数据连接:用来传送文件数据
- 控制连接:服务器打开端口号 21 等待客户端的连接,客户端主动建立连接后,使用这个连接将客户端的命令传送给服务器,并传回服务器的应答
- 根据 数据连接 (而非控制连接,因为控制连接一定是客户端主动建立的)是否是服务器端主动建立,FTP 有主动和被动两种模式
- 主动连接:服务器端主动建立数据连接,服务器端口号为20,客户端端口号随机
- 被动模式:客户端主动建立数据连接,客户端端口号由客户端自己指定,服务器端口号随机
3 SMTP、POP3、IMAP
- SMTP 是发送协议,POP3 和 IMAP 是读取协议
- 因为需要保证邮件传递可靠,所以都基于 TCP 连接
如何判断邮箱是否存在?利用 SMTP 协议
- 查找邮箱域名对应的 SMTP 服务器地址
- 尝试与服务器建立连接
- 连接成功后尝试向需要验证的邮箱发送邮件
- 根据返回结果判定邮箱地址的真实性
4 DHCP
- 动态主机配置协议提供了即插即用的连网方式,用户不再需要手动配置 IP 地址等信息
- 客户端发送 Discover 报文,该报文的目的地址为 255.255.255.255:67,源地址为 0.0.0.0:68,被放入 UDP 中,该报文被广播到同一个子网的所有主机上。如果客户端和 DHCP 服务器不在同一个子网,就需要使用中继代理
- DHCP 服务器收到 Discover 报文之后,发送 Offer 报文给客户端,该报文包含了客户端所需要的信息。因为客户端可能收到多个 DHCP 服务器提供的信息,因此客户端需要进行选择
- 如果客户端选择了某个 DHCP 服务器提供的信息,那么就发送 Request 报文给该 DHCP 服务器
- DHCP 服务器发送 Ack 报文,表示客户端此时可以使用提供给它的信息
五 传输层:TCP & UDP
1 TCP vs UDP
- UDP(User Datagram Protocol)是无连接的,尽最大可能交付,没有拥塞控制,面向报文(对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部),支持一对一、一对多、多对一和多对多的交互通信
- TCP(Transmission Control Protocol)是面向连接的,提供可靠交付,有流量控制,拥塞控制,提供全双工通信,面向字节流(把应用层传下来的报文看成字节流,把字节流组织成大小不等的数据块),每一条 TCP 连接只能是点对点的(一对一)
2 三次握手
三次握手的目的是建立可靠的通信信道,让双方确认自己与对方的发送与接收是正常的
- 第一次握手(SYN):Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
- 第二次握手(SYN/ACK):Client 确认自己发送、接收正常,对方发送、接收正常;Server 确认对方发送正常,自己接收正常
- 第三次握手(ACK):Client 确认自己发送、接收正常,对方发送、接收正常;Server 确认自己发送、接收正常,对方发送、接收正常
3 四次挥手
- 第一次挥手(FIN):客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送
- 第二次挥手(ACK):服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加 1 。和 SYN 一样,一个 FIN 将占用一个序号
- 第三次挥手(FIN/ACK):服务器-关闭与客户端的连接,发送一个 FIN 给客户端
- 第四次挥手(ACK):客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加 1
- 为什么客户端接收到服务器端的 FIN 报文后,进入 TIME_WAIT 状态而不是 CLOSED 状态?
是为了确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A等待一段时间就是为了处理这种情况的发生
4 TCP 如何实现可靠传输
- TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层
- TCP 报文段校验和。端到端的检验和,如果收到段的校验和有差错,TCP 将丢弃这个报文段
- TCP 的接收端会丢弃重复的数据
- 流量控制:当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失(接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率)
- 拥塞控制:当网络拥塞时,减少数据的发送(发送方的 发送窗口大小,即已发送未确认的大小 为 拥塞窗口 和接收方的 接收窗口 中较小的一个:
LastByteSent - LastByteAcked = min{receive_window, crowd_window}
) - 超时重传: 当 TCP 发出一个段后,启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到确认,将重发报文段
5 滑动窗口协议
- GBN 回退N步协议
- 限制发送方 已发送但未确认的分组数 最大为N
- 采用 累计确认 的机制
- 优点是接收方不需要缓存乱序分组,只需关注下一个分组的序号
- 缺点是丢弃乱序到达的分组,发生重传的分组数增加
- SR 选择重传协议
- 发送方只重传真正丢失的分组
- 发送方只确认已经到达的分组的序号,而不采用累计确认
- 接收方缓存失序到达的分组,同时接收方永远不会把分组失序地交给应用层,而是先要等待那些更早发送的分组到达
6 TCP 流量控制
- 流量控制是速度匹配服务,即发送方的发送速率和接收方的接收速率相匹配
- 接收窗口(接收方缓冲区空闲块大小)的计算方法
rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
RcvBuffer:接收方的缓冲区大小
LastByteRcvd:缓冲区接收到的从网络层到达的数据流的最后一个字节的编号
LastByteRead:接收方应用进程从缓存中读出的数据流的最后一个字节的编号
- 当接收方的接收窗口为0,即缓存满的时候,发送方继续发送只有一个字节数据的报文段,保证了后续的传输能正常进行
7 TCP 拥塞控制
- TCP 采用的是端到端的拥塞控制,而非网络辅助的拥塞控制,因为网络层不向端系统提供显式的网络拥塞反馈
- 对于不同原因引起的 Loss,处理策略不同:
如果收到3个重复 ACK(网络还能够传输一些报文段),设置 cwnd 为原来的一半,然后进入拥塞避免
如果发生超时(更严重的拥塞),设置 cwnd = 1,然后进入慢启动
-
慢启动
慢启动指,TCP 发送速率起始慢,但以指数增长
初始发送时,cwnd 通常设置为一个较小值 MSS,发送报文段后等待确认,如果收到确认则 cwnd 翻倍
到达慢启动阈值(如果丢包,设置慢启动阈值ssthresh = cwnd / 2
)时,停止慢启动,进入拥塞避免 -
拥塞避免
当 cwnd 到达慢启动阈值时,接近拥塞状态,此时 cwnd 线性增长
如果遇到 Loss,更新慢启动阈值为 cwnd / 2 ,根据产生 Loss 的原因采取不同的策略
(图中并不包含快速恢复,仅包含慢启动和拥塞避免)
- 快速恢复
- 当收到3个重复ACK时,ssthresh = cwnd / 2,cwnd = ssthresh + 3,然后重传丢失的报文段,加3是因为收到3个重复的ACK,表明有3个“老”的数据包离开了网络
- 再收到重复的ACK时,cwnd++
- 收到新的数据包的ACK时,cwnd = ssthresh。原因是确认了新的数据,说明重复ACK的数据都已收到,可以回到恢复之前的状态(拥塞避免状态)
六 常见问题
1 从输入 URL 地址到显示主页的过程
- 用户输入 URL,通过 UDP 连接向 DNS 服务器请求获取域名对应的 IP 地址
- 用户获得 IP 地址,与服务器建立 HTTP 连接(HTTP 基于 TCP 连接,三次握手)
- 用户向服务器发送 HTTP Request
- 服务器处理请求(这里又可以展开到 Spring MVC 的执行流程),返回 HTTP Response
- 浏览器渲染页面
2 HTTP:GET 和 POST 的区别
- GET 一般用于请求,POST 一般用于表单提交
- GET 方法是不安全的,因为会把请求参数拼接到 URL 的后面;POST
- 两种方法都是不安全的,因为 HTTP 本身是一个明文协议,每个 HTTP 请求和响应报文在网络上都是明文传播,无论是 URL、header 还是 body。想要安全应该使用 HTTPS
GET | POST | |
---|---|---|
作用 | 请求服务器返回资源 | 表单提交,将信息提交给服务器 |
请求参数 | 请求参数会拼接到 URL 后面 | 请求参数在请求体中,用户不可见 |
请求参数长度限制 | 参数拼接到 URL 中,长度有限 | 参数在请求体中,长度无限制 |
后退或刷新 | 无害 | 数据被重新提交 |