OSI与TCP/IP模型
TCP协议
TCP 协议的主要功能是完成对数据报的确认、流量控制和网络拥塞;自动检测数据报,并提供错误重发的功能;将多条路径传送的数据报按照原来的顺序进行排列,并对重复数据进行择取;控制超时重发,自动调整超时值;提供自动恢复丢失数据的功能。
- URG: 表示紧急指针是否有效。
- ACK: 表示确认号是否有效(携带ACK标志的TCP报文段称为确认报文段)。
- PSH: 提示接收端应用程序要立即从TCP接收缓冲区读走数据,以腾出空间接收后续的数据。(若应用 程序不读走数据,数据会一直留在TCP模块的接收缓冲区)。
- RST: 表示要求对方重新建立连接(携带RST标志的TCP报文段为复位报文段)。
- SYN: 表示请求建立一个连接(携带SYN标志的TCP报文段称为同步报文段)。
- FIN: 表示通知对方要关闭连接(携带FIN标志的TCP报文段为结束报文段)。
TCP协议如何保证传输可靠性
- 应用数据被分割成 TCP 认为最适合发送的数据块。
- TCP 给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传送给应用层。
- 校验和: TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
- TCP 的接收端会丢弃重复的数据。
- 流量控制: TCP 连接的每一方都有固定大小的缓冲空间,TCP的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议。 (TCP 利用滑动窗口实现流量控制)
- 拥塞控制: 当网络拥塞时,减少数据的发送。
- ARQ协议: 也是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认。在收到确认后再发下一个分组。
- 超时重传: 当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。
TCP 三次握手/四次挥手
三次握手
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
四次挥手
- 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
- 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
- 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
- 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态
- 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
问题:
为什么连接需要三次握手,而挥手需要四次?
答:当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:我们必须认为网络是不可靠的,最后一个ACK有可能会丢失,Server如果没有收到ACK,将不断重复发送FIN片段,所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
为什么不能两次握手?
答:网络传输可能延迟,如果只使用两次握手,无法确保数据完整,有序,还会造成不必要的开销。
拥塞控制
当出现丢包事件时,让发送方降低其发送速率,步骤分别有慢启动 -> 拥塞避免 > 快速恢复。
慢启动
TCP 发送方初始阶段不是线性地增加其发送率,而是以指数的速度增加,即每过一个 RTT(数据从网络一端传到另一端所需的时间)将 cwnd(拥塞窗口)值翻倍。
结束时机:
- 发生一个由超时指示的丢包事件(即拥塞),将ssthresh(阈值)状态变量设为cwnd值的一半,cwnd将设为1个MSS(最大传输大小),并重新开始慢启动。
- 当cwnd的值到达或超过ssthresh时,结束慢启动,TCP转移到拥塞避免模式。
- 若检测到3个冗余ACK,TCP执行快速重传,并进入快速恢复状态。
快速重传:
快重传算法要求首先接收方收到一个失序的报文段后就立刻发出重复确认,而不要等待自己发送数据时才进行捎带确认。
拥塞避免
当 cwnd<ssthresh 的时候,tcp 处于慢启动状态,否则,进入拥塞避免阶段。
拥塞避免的主要思想是加法增大,也就是 *cwnd 的值*不再指数级往上升,开始加法增加。此时当窗口中所有的报文段都被确认时,cwnd 的大小加 1MSS,即 TCP 发送方每收到一个新的确认 ACK,就将 cwnd 增加一个 MSS/cwnd 字节,cwnd 的值就随着 RTT 开始线性增加,这样就可以避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。
结束时机:
- 出现超时,ssthresh被设置为cwnd的一半,cwnd的值被置为1个MSS,进入慢启动。
- 收到3个冗余ACK,ssthresh被设置为cwnd的一半,cwnd为原来的一半加上3个MSS,进入快速恢复状态。
快速恢复
- 当收到3个重复ACK时,把ssthresh设置为cwnd的一半,把cwnd设置为ssthresh的值加3,然后重传丢失的报文段,即ssthresh=cwnd/2,cwnd=ssthresh+3;
- 收到重复的ACK时,cwnd增加1;
- 当收到新的数据包的ACK时,把cwnd设置为第一步中的ssthresh的值,再次进入拥塞避免状态;
- 出现超时,ssthresh被设置为cwnd的一半,cwnd设为1个MSS,进入慢启动状态。
TCP与UDP协议
| UDP | TCP | |
|---|---|---|
| 是否连接 | 无连接 | 面向连接 |
| 是否可靠 | 不可靠传输 | 可靠传输,使用流量控制和拥塞控制 |
| 连接对象个数 | 支持一对一,一对多,多对一和多对多交互通信 | 只能是一对一通信 |
| 传输方式 | 面向报文 | 面向字节流 |
| 首部开销 | 首部开销小,仅8字节 | 首部最小20字节,最大60字节 |
| 适用场景 | 适用于实时应用(QQ、IP电话、视频会议、直播等) | 适用于要求可靠传输的应用,例如文件传输 |
HTTP1.0、HTTP1.1和HTTP2.0
HTTP1.0和HTTP1.1
-
长连接
HTTP1.1开始支持长连接。
-
节约带宽
HTTP1.1支持只发送header信息。
-
HOST域
HTTP1.1必须要求传输HOST域。
-
缓存处理
HTTP1.1引入了更多的缓存控制策略。
-
错误通知的管理
在HTTP1.1中新增了24个错误状态响应码。
HTTP1.1和HTTP2.0
- 多路复用
- 头部数据压缩
- 服务器推送
HTTP状态码
常见状态码
| 状态码 | 含义 |
|---|---|
| 100 | 客户端应重新发送初始请求,并在请求中附上第一次请求时未提供的(可能很大或者包含敏感信息的)表示。 |
| 200 | 表示从客户端发来的请求在服务器端被正确处理。 |
| 201 | 当服务器依照客户端的请求创建了一个新资源时,发发送此响应代码。 |
| 204 | 无内容,服务器成功处理了请求,但没有返回任何内容。 |
| 301 | 永久性重定向,表示资源已被分配了新的 URL。 |
| 302 | 临时性重定向,表示资源临时被分配了新的 URL。 |
| 303 | 查看其它位置,表示资源存在着另一个 URL,应使用 GET 方法定向获取资源。 |
| 304 | 未修改,自从上次请求后,请求的网页未修改过。 |
| 307 | 临时重定向,和302含义相同。 |
| 400 | 服务器不理解请求的语法。 |
| 401 | 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 |
| 403 | 服务器拒绝请求。 |
| 404 | 未找到,服务器找不到请求的网页。 |
| 409 | 服务器在完成请求时发生冲突,服务器必须在响应中包含有关冲突的信息。 |
| 500 | 服务器遇到错误,无法完成请求。 |
| 502 | 服务器作为网关或代理,从上游服务器收到无效响应。 |
| 504 | 服务器作为网关或代理,但是没有及时从上游服务器收到请求。 |
Cookie和Session的区别
| Cookie | Session | |
|---|---|---|
| 存放位置 | 浏览器 | 服务器 |
| 安全性 | 不安全 | 安全 |
| 性能 | 对服务器压力小 | 当访问增多时,服务器压力大 |
| 数据大小 | 有大小限制,不能超过4K,很多浏览器最多保存20个cookie | 没有大小限制 |
HTTP和HTTPS的区别
-
端口 :HTTP的URL由“http://”起始且默认使用端口80,而HTTPS的URL由“https://”起始且默认使用端口443。
-
安全性和资源消耗:
HTTP协议运行在TCP之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS 运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS高,但是 HTTPS 比HTTP耗费更多服务器资源。
- 对称加密:密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES等;
- 非对称加密:密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。
在浏览器中输入URL地址到显示主页的过程
-
首先进行域名解析,域名解析具体过程讲一下:
- 浏览器搜索自己的DNS缓存,缓存中维护一张域名与IP地址的对应表;
- 若没有,则搜索操作系统的DNS缓存;
- 若没有,则操作系统将域名发送至本地域名服务器(递归查询方式),本地域名服务器查询自己的DNS缓存,查找成功则返回结果,否则,通过以下方式迭代查找:
- 本地域名服务器向根域名服务器发起请求,根域名服务器返回com域的顶级域名服务器的地址;
- 本地域名服务器向com域的顶级域名服务器发起请求,返回权限域名服务器地址;
- 本地域名服务器向权限域名服务器发起请求,得到IP地址。
- 本地域名服务器将得到的IP地址返回给操作系统,同时自己将IP地址缓存起来; 操作系统将IP地址返回给浏览器,同时自己也将IP地址缓存起来;
至此,浏览器已经得到了域名对应的 IP 地址。
-
浏览器发起HTTP请求;
-
接下来到了传输层,选择传输协议,TCP或者UDP,TCP是可靠的传输控制协议,对HTTP请求进行封装,加入了端口号等信息;
-
然后到了网络层,通过IP协议将IP地址封装为IP数据报;然后此时会用到ARP协议,主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址,找到目的MAC地址;
-
接下来到了数据链路层,把网络层交下来的IP数据报添加首部和尾部,封装为MAC帧,现在根据目的mac开始建立TCP连接,三次握手(详细讲)。
-
建立了TCP连接后,如果使用HTTPS,则需要进行SSL握手,沟通加密参数(如,SSL版本)以及交换秘钥,握手完成后,报文会在发送给TCP之前在SSL层进行加密。
-
建立了TCP连接便可以发送HTTP请求了,HTTP请求通过TCP协议发到Server端。
-
接收端在收到物理层上交的比特流后,根据首尾的标记,识别帧的开始和结束,将中间的数据部分上交给网络层,然后层层向上传递到应用层;
-
服务器响应请求并请求客户端要的资源,传回给客户端;
-
断开TCP连接,浏览器对页面进行渲染呈现给客户端。
总体来说分为以下几个过程:
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回HTTP报文
- 浏览器解析渲染页面
- 连接结束