客户端和服务器交互的基本模型 | 青训营笔记

206 阅读9分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第5天。

客户端和服务器交互的基本模型

客户端:可以向服务器发请求,并接收返回的内容进行处理。

服务器端:能够接收客户端请求,并且把相关资源信息返回给客户端的。

当用户在地址栏中输入网址,到最后看到页面,中间都经历了什么?

  1. URL地址解析

  2. DNS域名解析

  3. 和服务器建立TCP连接(三次握手)

  4. 把客户端信息传递给服务器(发送HTTP请求) (request请求阶段)


  5. 服务器得到并处理请求(HTTP响应内容) (response响应阶段)

  6. 客户端渲染服务器返回的内容

  7. 和服务器断开TCP连接(四次挥手)

URI/URL/URN

  • URL(Uniform Resource Locator):统一资源定位符,格局这个地址能找到对应的资源。
  • URN(Uniform Resource Name):统一资源名称,一般指国际上通用的(标准的)一些名字(例如:国际统一发版的编号)
  • URI(Uniform Resource Identifier):统一资源标识符,URL和URN是URI的子集。

一个完整的URL包含的内容

www.zhufengpeoxun.cn:80/stu/index.h…

  • 协议:传输协议是能够把客户端和服务器通信的信息,进行传输的工具。

    • http 超文本传输协议,除了传递文本,还可以传递媒体资源文件及XML格式数据。
    • https 更加安全的http,一般涉及支付的网站都采用https协议。(s是ssl加密传输)
    • ftp文件传输协议(一般应用于把本地资源上传到服务器端)
  • 域名

    • 顶级域名 qq.com
    • 一级域名 www.qq.com
    • 二级域名 sports.qq.com
    • 三级域名 kbs.sports.qq.com
    • .com 国际域名
    • .cn 中文域名
    • .org 组织
  • 端口号(80):端口号取值范围0~65535。用端口号来区分同一台服务器上的不同项目

    • http默认端口号80
    • https默认端口号443
    • ftp默认端口号21
    • 如果项目采用的是默认端口号,我们在书写地址的时候不用加端口号,浏览器再发送请求的时候会帮我们默认给加上。
  • 请求资源路径名称(/stu/index/html)

    • 默认的路径或名称
    • 注意伪URL地址的处理(URL重写技术是为了增加SEO搜索引擎优化的,动态的网址一般不能被搜索引擎收录,所以我们要把动态网址静态化,此时需要的是重写URL)
  • 问号传参信息(?from=wx&lx=1)

    • 用于客户端和服务器端以及不同页面之间的通信、信息传输
  • 哈希值(#zhenyu)

    • 也能充当信息传输的机制
    • 锚点定位
    • 基于哈希实现路由管控

ps.给服务器通往后,会有两个IP地址

  • 内网IP:局域网内访问
  • 外网IP:外部用户可以基于外网IP访问到服务器

ps.服务器接收到请求后

  1. 根据端口号找到对应的项目
  2. 根据请求资源的路径名称找到资源文件
  3. 读取资源文件中的内容
  4. 把内容返回

DNS域名解析

DNS服务器:域名解析服务器,在服务器上存储着域名,域名对应服务器外网IP的相关记录。

而我们发送请求时所谓的DNS解析,其实就是根据域名在DNS服务器上查找到对应服务器的外网IP。

每一次请求都要到DNS服务器中进行一次解析,这个过程要耗费一些时间=>前端性能优化之DNS预获取。

DNS优化:

  • DNS缓存(一般浏览器会在第一次解析后,默认建立缓存,时间很短,只有一分钟左右)
  • 减少DNS解析次数(一个网站中我们需要发送请求的域名和服务器尽可能少即可)
  • DNS预获取(dns-prefetch)在页面加载开始的时候,就把当前页面中需要访问其他域名和服务器信息进行提前DNS解析,以后加载到具体内容部分可以不用解析了

TCP三次握手和HTTP报文

三次握手

三次握手发生在信息传输前(建立连接的过程)。

  • 第一次握手:客户端发送syn包(Seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
  • 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(Seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
  • 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

三次握手为了确认连接成功和接下来的传输没有任何问题。

syn=1,1的传输速率高

发送HTTP请求

http报文(请求报文+响应报文):

  • 请求报文:所有经过传输协议,客户端传递给服务器的内容,都被称为请求报文。

    • 起始行
    • 请求头(请求首部)
    • 请求主体
  • 响应报文:所有经过传输协议,服务器返回给客户端的内容,都被称为响应报文。

    • HTTP状态码
    • 响应头
    • 响应主体

TCP四次挥手(断开连接)

四次挥手

四次挥手发生在信息传输过程中。 (每一次挥手都是在记录一下当前一个完整的请求+响应的进行状态)。

  • 第一次挥手:客户端发送一个FIN,用来关闭客户端到服务器的数据传送,也就是客户端告诉服务器:我已经不会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,客户端依然会重发这些数据),但是,此时客户端还可 以接受数据。 FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  • 第二次挥手:服务器收到FIN包后,发送一个ACK给对方并且带上自己的序列号seq,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
  • 第三次挥手:服务器发送一个FIN,用来关闭服务器到客户端的数据传送,也就是告诉客户端,我的数据也发送完了,不会再给你发数据了。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  • 第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

TCP 使用四次挥手的原因是因为 TCP 的连接是全双工的,所以需要双方分别释放到对方的连接,单独一方的连接释放,只代表不能再向对方发送数据,连接处于的是半释放的状态。

最后一次挥手中,客户端会等待一段时间再关闭的原因,是为了防止发送给服务器的确认报文段丢失或者出错,从而导致服务器 端不能正常关闭。

为什么挥手要四次?

本质的原因是tcp是全双公的,要实现可靠的连接关闭,A发出结束报文FIN,收到B确认后A知道自己没有数据需要发送了,B知道A不再发送数据了,自己也不会接收数据了,但是此时A还是可以接收数据,B也可以发送数据。当B发出FIN报文的时候此时两边才会真正的断开连接,读写分开。

TCP长连接:一直保持客户端和服务器端连接不中断。

为什么建立连接是三次握手,关闭连接却是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。