主题
网络
1. UDP
1.1 面向报文
UDP
是⼀个面向报⽂ (报⽂可以理解为⼀段段的数据) 的协议 。意思就是 UDP
只是报⽂的搬运⼯,不会对报⽂进行任何拆分和拼接操作
具体来说
- 在发送端,应用层将数据传递给传输层的
UDP
协议,UDP
只会给数据增加⼀个UDP
头标识下是UDP
协议,然后就传递给网络层了 - 在接收端, 网络层将数据传递给传输层,
UDP
只去除IP
报⽂头就传递给应用层,不会任何拼接操作
1.2 不可靠性
UDP
是⽆连接的,也就是说通信不需要建立和断开连接。UDP
也是不可靠的 。协议收到什么数据就传递什么数据, 并且也不会备份数据,对⽅能不能收到是不关⼼的UDP
没有拥塞控制,⼀ 直会以恒定的速度发送数据 。即使网络条件不好,也不会对发送速率进行调整 。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景 ( 比如电话会议) 就需要使用UDP
而不是TCP
1.3 高效
因为 UDP
没有 TCP
那么复杂, 需要保证数据不丢失且有序到达 。所以 UDP
的头部开销⼩,只有⼋字节,相比 TCP
的至少⼆⼗字节要少得多,在传输数据报⽂时是很高效的
头部包含了以下几个数据
- 两个⼗六位的端⼝号 ,分别为源端⼝ ( 可选字段) 和目标端⼝ 整个数据报⽂的长度
- 整个数据报⽂的检验和 (
IPv4
可选 字段), 该字段用于发现头部信息和数据中的错误
1.4 传输方式
UDP
不止⽀持⼀对⼀的传输⽅式, 同样⽀持⼀对多, 多对多, 多对⼀的⽅式,也就是说 UDP
提供了单播, 多播,⼴播的功能
2. TCP
2.1 头部
TCP
头部比 UDP
头部复杂的多
对于 TCP
头部来说, 以下⼏个字段是很重要的:
Sequence number
, 这个序号保证了TCP
传输的报⽂都是有序的,对端可以通过序号顺序的拼接报⽂Acknowledgement Number
, 这个序号表示数据接收端期望接收的下⼀个字节的编号是多少, 同时也表示上⼀个序号的数据已经收到Window Size
, 窗⼝大⼩ ,表示还能接收多少字节的数据,用于流量控制
标识符
URG=1
:该字段为⼀表示本数据报的数据部分包含紧急信息, 是⼀个高优先级数据报⽂,此时紧急指针有效 。紧急数据⼀定位于当前数据包数据部分的最前面, 紧急指针标明了紧急数据的尾部。ACK=1
:该字段为⼀表示确认号字段有效 。此外,TCP
还规定在连接建立后传送的所有报⽂段都必须把ACK
置为⼀PSH=1
:该字段为⼀表示接收端应该立即将数据push
给应用层,而不是等到缓冲区满后再提交。RST=1
:该字段为⼀表示当前TCP
连接出现严重问题, 可能需要重新建立TCP
连接,也可以用于拒绝非法的报⽂段和拒绝连接请求。SYN=1
: 当SYN=1
,ACK=0
时,表示当前报⽂段是⼀个连接请求报⽂ 。当SYN=1
,ACK=1
时,表示当前报⽂段是⼀个同意建立连接的应答报⽂ 。FIN=1
:该字段为⼀表示此报⽂段是⼀个释放连接的请求报⽂
2.2 状态机
HTTP
是⽆连接的,所以作为下层的 TCP
协议也是⽆连接的, 虽然看似 TCP
将两端连接了起来,但是其实只是两端共同维护了⼀个状态
TCP
的状态机是很复杂的, 并且与建立断开连接时的握手息息相关,接下来就来详细描述下两种握手。
在这之前需要了解⼀个重要的性能指标 RTT
。该指标表示发送端发送数据到接收到对端数据所需的往返时间
建立连接三次握手
在 TCP
协议中, 主动发起请求的⼀端为客户端,被动连接的⼀端称为服务端 。不管是客户端还是服务端, TCP
连接建立完后都能发送和接收数据,所以 TCP
协议。 起初,两端都为 CLOSED
状态 。在通信开始前, 双⽅都会创建 TCB
。 TCB
后遍进⼊ LISTEN
状态, 此时开始等待客户端发送数据
- 第⼀次握手
客户端向服务端发送连接请求报⽂段 。该报⽂段中包含自身的数据通讯初始序号 。请求发送后,客户端便进⼊ SYN-SENT
状态,x 表示客户端的数据通信初始序号。
- 第二次握手
服务端收到连接请求报⽂段后,如果同意连接,则会发送⼀个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进⼊ SYN-RECEIVED
状态。
- 第三次握手
当客户端收到连接同意的应答后, 还要向服务端发送⼀个确认报⽂ 。客户端发完这个报⽂段后便进⼊ ESTABLISHED
状态, 服务端收到这个应答后也进⼊ ESTABLISHED
状态,此时连接建立成功。
PS:第三次握⼿可以包含数据, 通过 TCP
快速打开 ( TFO
) 技术 。其实只要涉及到握 ⼿的协议,都可以使用类似 TFO
的⽅式,客户端和服务端存储相同 cookie
,下次握⼿ 时发出 cookie
达到减少 RTT
的目的
你是否有疑惑明明两次握手就可以建立起连接,为什么还需要第三次应答?
因为这是为了防止失效的连接请求报⽂段被服务端接收,从而产生错误
可以想象如下场景 。客户端发送了⼀个连接请求
A
,但是因为网络原因造成了超时, 这时TCP
会启动超时重传的机制再次发送⼀个连接请求B
。此时请求顺利到达服务端, 服务端应答完就建立了请求 。如果连接请求A
在两端关闭后终于抵达了服务端,那么这时服务端会认为客户端⼜需要建立TCP
连接,从而应答了该请求并进⼊ESTABLISHED
状态 。此时客户端其实是CLOSED
状态,那么就会导致服务端⼀直等待, 造成资源的浪费
PS:在建立连接中,任意⼀端掉线,
TCP
都会重发SYN
包,⼀般会重试五次,在建立连接中可能会遇到SYN FLOOD
攻击 。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求
断开链接四次握手
TCP
是全双⼯的,在断开连接时两端都需要发送 FIN
和 ACK
。
- 第⼀次握手
若客户端 A
认为数据发送完成,则它需要向服务端 B
发送连接释放请求。
- 第二次握手
B
收到连接释放请求后,会告诉应用层要释放 TCP
链接 。然后会发送 ACK
包, 并进⼊ CLOSE_WAIT
状态,表示 A
到 B
的连接已经释放,不接收 A
发的数据了 。但是因为 TCP
连接时双向的,所以 B
仍旧可以发送数据给 A
。
- 第三次握手
B
如果此时还有没发完的数据会继续发送, 完毕后会向 A
发送连接释放请求,然后 B
便进⼊ LAST-ACK
状态。
PS:通过延迟确认的技术 ( 通常有时间限制, 否则对⽅会误认为需要重传),可以将第⼆次和第三次握⼿合并,延迟 ACK
包的发送。
- 第四次握手
A
收到释放请求后, 向 B
发送确认应答,此时 A
进⼊ TIME-WAIT
状态 。该状态会持续 2MSL
( 最大段生存期,指报⽂段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B
的重发请求的话,就进⼊ CLOSED
状态 。当 B
收到确认应答后,也便进⼊ CLOSED
状态。
为什么
A
要进⼊TIME-WAIT
状态, 等待2MSL
时间后才进⼊CLOSED
状态?为了保证
B
能收到A
的确认应答 。若A
发完确认应答后直接进⼊CLOSED
状态, 如果确认应答因为网络问题⼀直没有到达,那么会造成B
不能正常关闭
3. HTTP
HTTP
协议是个⽆状态协议,不会保存状态
3.1 Post 和 Get 的区别
Get
请求能缓存,Post
不能Post
相对Get
安全⼀点点, 因为Get
请求都包含在URL
里,且会被浏览器保存历史纪录,Post
不会,但是在抓包的情况下都是⼀样的。Post
可以通过request body
来传输比Get
更多的数据,Get
没有这个技术URL
有长度限制,会影响Get
请求,但是这个长度限制是浏览器规定的,不是RFC
规定的Post
⽀持更多的编码类型且不对数据类型限制
3.2 常见状态码
2XX 成功
200
OK
,表示从客户端发来的请求在服务器端被正确处理204
No content
,表示请求成功,但响应报文不含实体的主体部分205
Reset Content
,表示请求成功,但响应报文不含实体的主体部分,但是与204
响应不同在于要求请求方重置内容206
Partial Content
, 进⾏范围请求
3XX 重定向
301
moved permanently
,永久性重定向,表示资源已被分配了新的URL
302
found
, 临时性重定向,表示资源临时被分配了新的URL
303
see other
,表示资源存在着另⼀个URL
,应使用GET
方法丁香获取资源304
not modified
,表示服务器允许访问资源,但因发生请求未满足条件的情况307
temporary redirect
, 临时重定向,和302
含义类似,但是期望客户端保持请求方法不变向新的地址发出请求
4XX 客户端错误
400
bad request
,请求报文存在语法错误401
unauthorized
,表示发送的请求需要有通过HTTP
认证的认证信息403
forbidden
,表示对请求资源的访问被服务器拒绝404
not found
,表示在服务器上没有找到请求的资源
5XX 服务器错误
500
internal sever error
,表示服务器端在执⾏请求时发生了错误501
Not Implemented
,表示服务器不支持当前请求所需要的某个功能503
service unavailable
,表明服务器暂时处于超负载或正在停机维护, 无法处理请求
3.3 HTTP 首部
通用字段 | 作用 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 浏览器想要优先使用的连接类型, 比如 keep-alive |
Date | 创建报文时间 |
Pragma | 报文指令 |
Via | 代理服务器相关信息 |
Transfer-Encoding | 传输编码方式 |
Upgrade | 要求客户端升级协议 |
Warning | 在内容中可能存在错误 |
请求字段 | 作用 |
---|---|
Accept | 能正确接收的媒体类型 |
Accept-Charset | 能正确接收的字符集 |
Accept-Encoding | 能正确接收的编码格式列表 |
Accept-Language | 能正确接收的语⾔列表 |
Expect | 期待服务端的指定⾏为 |
From | 请求方邮箱地址 |
Host | 服务器的域名 |
If-Match | 两端资源标记比较 |
If-Modified-Since | 本地资源未修改返回 304 ( 比较时间) |
If-None-Match | 本地资源未修改返回 304 ( 比较标记) |
User-Agent | 客户端信息 |
Max-Forwards | 限制可被代理及网关转发的次数 |
Proxy-Authorization | 向代理服务器发送验证信息 |
Range | 请求某个内容的⼀部分 |
Referer | 表示浏览器所访问的前⼀个页面 |
TE | 传输编码方式 |
响应字段 | 作用 |
---|---|
Accept-Ranges | 是否支持某些种类的范围 |
Age | 资源在代理缓存中存在的时间 |
ETag | 资源标识 |
Location | 客户端重定向到某个 URL |
Proxy-Authenticate | 向代理服务器发送验证信息 |
Server | 服务器名字 |
WWW-Authenticate | 获取资源需要的验证信息 |
实体字段 | 作用 |
---|---|
Allow | 资源的正确请求方式 |
Content-Encoding | 内容的编码格式 |
Content-Language | 内容使用的语⾔ |
Content-Length | request body 长度 |
Content-Location | 返回数据的备用地址 |
Content-MD5 | Base64 加密格式的内容 MD5 检验值 |
Content-Range | 内容的位置范围 |
Content-Type | 内容的媒体类型 |
Expires | 内容的过期时间 |
Last_modified | 内容的最后修改时间 |
4. DNS
DNS
的作用就是通过域名查询到具体的 IP
。
因为 IP
存在数字和英文的组合 ( IPv6
), 很不利于⼈类记忆,所以就出现了域名 。你可以把域名看成是某个 IP
的别名, DNS
就是去查询这个别名的真正名称是什么
在 TCP
握手之前就已经进⾏了 DNS 查询, 这个查询是操作系统自己做的。当你在浏览器中想访问 www.google.com
时,会进⾏⼀下操作
操作系统会首先在本地缓存中查询,没有的话会去系统配置的 DNS 服务器中查询,如果这时候还没得话,会直接去 DNS
根服务器查询, 这⼀步查询会找出负责 com
这个⼀级域名的服务器,然后去该服务器查询 google
这个⼆级域名,接下来三级域名的查询其实是我们配置的,你可以给 www
这个域名配置⼀个 IP
,然后还可以给别的三级域名配置⼀个 IP
以上介绍的是 DNS
迭代查询, 还有种是递归查询, 区别就是前者是由客户端去做请求,后者是由系统配置的 DNS
服务器做请求,得到结果后将数据返回给客户端。