TCP、UDP、HTTP面试内容(常问点)
写在前面
- 博客首页
- 内容由思维导图转换而来
计算机网络
TCP三次握手,四次挥手
三握
最开始,CS都处于关闭状态,S需要监听所到来的请求
第一次 C –> S,客户端发送了SYN包,包含SYN=1,并生成了客户端的序列号,告诉服务端,我要和你建立连接
第二次 S –> C,服务端收到SYN包后,向客户端发送SYN + ACK 包,包含ACK = 1,和生成服务端的序列号,以及将客户端的序列号+1返回(确认应答号),告诉客户端,我能收到你的报文,这一步S确认能收到C的报文(但是不知道C能不能收到我的)
第三次 C –> S,客户端收到SYN + ACK报文后,向服务端发送ACK报文,包含ACK = 1,SYN = 1,将接收到的服务端序列号 + 1 放回,这一步之后,客户端确认了我能发能接,变为建立连接状态,等到服务端收到后,服务端也确定客户端能收到,变为建立连接状态
为什么不是二次?四次?
- 所谓两次就是,C –> S时,S就变为E状态,如果C因为多次发送,就会导致S创建多个连接,资源浪费,并且无法阻止这种历史连接导致的服务端重复建立连接问题。
- 所谓四次就是,在原第二次连接时,S – > C时,在多一个S –> C,将确认应答号,和自身序列号分开发送,这完全没必要,三次已经达到理论最优了。
如果中途出现报文丢失?
- 第一次SYN丢失的话,C会重发
- 第二次SYN + ACK 丢失的话,C会重发,S也会重发,因为客户端不确认S收到没,S也不确认C收到没,重发次数有设定
- 第三次ACK丢失的话,S会重发,因为S不确定C收到没有
四挥
- 比三次握手多一次的原因是,在S接收到C发来的FIN报文时,会先发送一个ACK响应报文,表示S自己已经收到FIN报文,但是S自身关闭是一个过程,会进行一些数据处理或报文发送,等待这个结束之后,才会发送一个FIN报文给C,告诉C我关闭成功
- 在第四次C–>S时,客户端并不是马上进入关闭状态,而是会等待一段时间再关闭,时间为2 * 报文最大生存时间(MSL),之所以是这个时间,是因为容错,需要防止从S–>C的FIN报文丢失,这个时候可以容忍S重传一次FIN报文,不是4 8 是因为概率小,再多就直接考虑换网吧
TCP的超时重传、快速重传、拥塞控制、流量控制
超时重传
- A–>B 发送SYN报文时,设置一个定时器,当在这段时间内没有收到B–>A的ACK报文,就会重传
- 超时时间设定,是TCP通过多次采用,平滑计算得到一个 来回的平均值后,超时时间大于这个值一点点来确认
快速重传
- 不以时间为驱动,而是以数据为驱动的重传,在超时时间内,通过接收情况,来判断是否存在丢失的报文
- SACK 方法:在原来基础上,添加了SACK段,回传给发送方时,告诉发送方接受了哪些数据,这样发送方可以选择性重传丢失的数据包
- D-SACK方法:回传给发送方时,可以告诉发送方哪些数据重复传了(这里的SACK就是D-SACK),来避免因为网络导致的多次重发
滑动窗口
- 相当于,将原来一问一答的等待模式,变成多问多答,就是相当于多封装几个TCP报文段发送和接收
- 而滑动窗口的事先上,依赖TCP报文段中的window属性大小,接收方回传给发送端,告诉发送方可以接收多少
流量控制
- 利用滑动窗口这种机制,让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制
拥塞控制
即使有了滑动窗口和流量控制,但是当网络发生数据包时延、丢失包,发送方会重发,越传网络越堵,最后恶行循环,拥塞控制可以避免网络中占满了发送方的数据包
引入了拥塞窗口,通过比较接收窗口和拥塞窗口,去最小值回传给发送方,来控制发送方的可用窗口传输大小
四大算法
慢启动:防止一开始就发送大量数据,当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1,呈现指数级增长,一直达到慢启动门限阈值
拥塞避免:当cwnd超过慢启动门限阈值后,每当收到一个 ACK 时,cwnd 增加 1/cwnd,那么cwnd个ACK的话,就是增加1,呈现线性增长
拥塞发生:慢慢地发生拥塞后,拥塞导致丢包重传
- 当发生超时重传时,ssthresh重置为cwnd/2,cwnd重置为初始值,然后进入慢启动,这种比较激进,可能导致卡顿
- 当发生快速重传时,将cwnd = cwnd/2,然后ssthresh=cwnd,采用快速恢复算法
快速恢复:在处理完cwnd和ssthresh值后,假设此时接收到了n个数据包,那么cwnd = ssthresh + n,再次接收到ack时,如果为重复的cwnd+1,如果是新的,那么将cwnd置为ssthesh的值,此时进入拥塞避免阶段
浏览器输入连接,是如何执行的
- 首先就是解析URL,获取要发给服务器端的信息,并生成HTTP报文
- 要进行DNS域名解析,获取得到IP地址
- 将HTTP的传输工作交给操作系统中的协议栈(包括Tcp,udp,ip,arp等)
- 经过TCP的三次握手建立连接,TCP模块再执行连接、收发、断开等阶段操作时,还需要IP模块将数据封装成网络包发送给通信对象。
- 包裹了IP头部之后,接下来还需要在前面包裹mac头,来确定mac地址(IP可变,mac不可变)
- 最后会经过网卡转换为电信号,以及交换机和路由器达到服务端,然后就是一个反向的过程(一点点的拆包)
执行流程
- DNS域名服务器分为dot根域名、com顶级域名服务器、xxx.com权威域名服务器,
- 客户端发送一个DNS域名解析请求,首先会问操作系统有没有缓存记录当前域名的IP,没有的话,再取host文件中找找,然后再去找本地域名服务器,再去找根域名,根域名不记录对应关系,但是指明方向到com域名服务器,再给踢皮球踢到权威域名服务器(响应方),这其中任何一个环节都会有缓存,最后解析出真正的IP(浏览器缓存 –> 本地host文件 –> 本地DNS域名服务器 –> 根域名服务器(不存放,指方向) –> com顶级域名服务器 –> 权威域名服务器(服务方))
- 拿到IP地址后,会将数据包发给操作系统的协议栈(包含TCP或UDP负责收发数据,以及往下的IP(负责将收到的流数据切割成数据包然后收发),这两者是配合起来实现数据的收发)
- HTTP是基于TCP来进行可靠传输的,那么这里也会进行TCP三次握手建立连接,然后委托 IP 模块将数据封装成网络包发送给通信对象,这个时候Http报文外已经包裹了TCP报文头和IP报文头,这个时候还需要包裹上MAC报文头,来确定源MAC地址和目标MAC地址
- 然后由网卡将数字信息转化为电信息,再经过交换机,查询mac地址表,找到对应的网络端口,再由路由器转发出去,去找到对应的服务器
- 最后依次拆包,拆初mac,ip,tcp拿到http报文内容进行处理,然后响应,一次装箱
如何保持登录态?见下方cookie session token
Http
请求方式
- get:对服务器获取资源的简单请求
- post:向服务端提交数据请求
- put:修改指定资源
- delete:删除指定资源
- head:获取url标记资源的头部
- connect:用于代理服务器
- trance:用于环路测试
- options:返回所有可用的方法
状态码
1XX
- 101:切换请求协议
2XX
- 200: 成功响应
3XX
- 301:请求资源永久移动,返回新uri
- 302:请求资源临时移动,继续使用原有uri
4XX
- 400:badRequest 客户端请求语法错误,服务端无法理解
- 401:需要重新认证
5XX
- 服务器内部报错,比如空指针异常等
- 504:网关超时
- 500:服务器出错
报文结构
HTTP请求报文
1
2
3
4GET /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.dedenotes.com
Accept-Language: en, mi报文首部
第一行,请求行
- 方法字段:GET/POST
- URL字段
- HTTP协议版本字段
首部行(后面可)
空行
报文主体
HTTP响应报文
1
2
3
4
5
6
7
8
9HTTP/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/plain报文首部
状态行
- 协议版本字段 HTTP/1.0
- 首部行
首部行
实体
空行
报文主体
关于首部行:- 首部行首部可以分为四种首部,请求首部、响应首部、通用首部和实体首部。通用首部和实体首部在请求报文和响应报文中都可以设置,区别在于请求首部和响应首部- 常见的请求首部有 Accept 可接收媒体资源的类型、Accept-Charset 可接收的字符集、Host 请求的主机名
HTTP各个版本区别
Http1.0:短连接,每次请求产生一个,可以通过设置 connection:keep-aliave强制开启长连接
Http1.1
- 长连接,TCP连接默认不关闭,可以被多个请求复用
- 管道机制,在同一个TCP连接内,可以发送多个请求
Http2
- 1.1的头是ASSIC编码格式,数据体用文本或者二进制,到了2.0就是全二进制了
- 采用多路复用,就是C和S都可以在一个TCP连接里发送多个请求或响应,并且不需要按照顺序
- 允许服务端主动向客户端推送,
Http3.0
- HTTP/3主要有两大变化,传输层基于UDP、使用QUIC(Quick UDP Connections)保证可靠性
- HTTP3 首先要建立好 HTTP 2 连接,然后发送 HTTP 2 扩展帧,这个帧包含IP和端口,浏览器收到扩展帧,使用该 IP 和端口,使用 QUIC 建立连接,如果成功,断开 HTTP2,升级为HTTP3
根本区别:关键需要记住 HTTP/1.0 默认是短连接,可以强制开启,HTTP/1.1 默认长连接,HTTP/2.0 采用多路复用。
HTTP与HTTPS
HTTP是明文传输,HTTPS 在 TCP 三次握手之后,还需进行 SSL/TLS 的握手过程,才可进入加密报文传输
HTTP端口是80,HTTPS的端口是443
HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信
HTTPS的工作流程
客户端发起HTTP请i去,连接到服务端的443端口
服务端由一套CA(包括公钥、证书颁发机构、失效日期),服务端将自己的CA返回给客户端(包含公钥,但是私钥在客户端那)
客户端拿到CA后,会验证证书合法性,通过后,用公钥加密生成的随机对称密钥,客户端将公钥加密后的对称密钥发给服务器
服务器接收到密文密钥后,用自己的私钥来进行非对称解密,解密后得到客户端的密钥,然后用客户端的密钥对数据进行加密,这样传输的数据都是密文,服务器将加密后的密文发送客户端
客户端收到后,用自己生成的那个对称密钥进行解密,得到数据。
无状态与Session、Cookie和token
无状态:所谓无状态指的是客户端的状态,HTTP协议中服务端不会保存客户端任何信息,缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大
Cookie:比本质就是一段文本串,当客户端第一次请求时,其由服务端生成发给客户端,客户端浏览器保存Cookie,用于下次登陆,不在需要重新登陆,并且不允许垮域访问
session:另一种记录客户状态的机制,保存在服务器上,服务器把客户端传来的信息,以这种形式记录在服务器。
token,令牌,是用户身份的验证方式,token安全行比session好,包含认证授权,支持跨域,可以用于分布式环境
大部分情况下呢,都是Cookie和session打配合,由cookie保存sessionId来实现