• 面试---计算机网络


    一、TCP三次握手除了建立连接(发送SYN、SEQ、ACK),还会完成什么工作(也就是在报文的传输过程中还会携带什么信息)

    (1)最大报文段长度(MSS)选项
      TCP连接初始化时,通信双方使用该选项来协商最大报文段长度,防止IP分片。每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的MSS值,则MSS就定为默认值536字节(这个默认值允许20字节的IP首部和20字节的TCP首部以适合576字节IP数据报)。

    (2)kind=3,窗口扩大因子选项(WSOPT)
      TCP连接初始化时,通信双方使用该选项来协商接收窗口的扩大因子。在TCP的头部中,接收窗口大小是用16位表示的,故最大为65535字节,但实际上TCP模块允许的接收窗口(滑动窗口)大小远不止这个数(为了提高TCP通信的吞吐量)。窗口扩大因子解决了这个问题。

    (3)选择性确认(SACK-permitted)选项
      TCP通信时,如果某个TCP报文段丢失,则TCP会重传最后被确认的TCP报文段后续的所有报文段,这样原先已经正确传输的TCP报文段也可能重复发送,从而降低了TCP性能。SACK技术正是为改善这种情况而产生的,它使TCP只重新发送丢失的TCP报文段,而不用发送所有未被确认的TCP报文段。选择性确认选项用在连接初始化时,表示是否支持SACK技术。我们可以通过修改 /proc/sys/net/ipv4/tcp_sack 内核变量来启用或关闭选择性确认选项。

    第一个详解:

      在建立TCP连接的同时,也可以确定发送数据包的单位,我们也可以称其为“最大消息长度”(MSS:Maximum Segment Size)。最理想的情况是,最大消息长度正好是IP中不会被分片处理的最大数据长度。

      TCP在传送大量数据时,是以MSS的大小将数据进行分割发送的。进行重发时也是以MSS为单位。

      MSS是在三次握手的时候,在两端主机之间被计算得出。两端主机在发出建立连接的请求时,会在TCP首部中写入MSS选项,告诉对方自己的接口能够适应的MSS大小。然后会在两者之间选择一个较小的值投入使用

    二、TCP的选项有哪些内容

    1、kind=0,选项表结束(EOP)选项
      告知选项结束

    2、kind=1,空操作(NOP)选项
      没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍

    3、kind=2,最大报文段长度(MSS)选项
      TCP连接初始化时,通信双方使用该选项来协商最大报文段长度,防止IP分片。每一方都有用于通告它期望接收的MSS选项(MSS选项只能出现在SYN报文段中)。如果一方不接收来自另一方的MSS值,则MSS就定为默认值536字节(这个默认值允许2 0字节的IP首部和2 0字节的TCP首部以适合576字节IP数据报)。

    4、kind=3,窗口扩大因子选项(WSOPT)
      TCP连接初始化时,通信双方使用该选项来协商接收窗口的扩大因子。在TCP的头部中,接收窗口大小是用16位表示的,故最大为65535字节,但实际上TCP模块允许的接收窗口(滑动窗口)大小远不止这个数(为了提高TCP通信的吞吐量)。窗口扩大因子解决了这个问题。
      假设TCP头部中的接收通告窗口大小是N,窗口扩大因子(移位数)是M,那么TCP报文段的实际接收通告窗口大小是N*2M,或者说N左移M位。注意,M的取值范围是0~14。

    5、kind=4,选择性确认(SACK-permitted)选项
      TCP通信时,如果某个TCP报文段丢失,则TCP会重传最后被确认的TCP报文段后续的所有报文段,这样原先已经正确传输的TCP报文段也可能重复发送,从而降低了TCP性能。SACK技术正是为改善这种情况而产生的,它使TCP只重新发送丢失的TCP报文段,而不用发送所有未被确认的TCP报文段。选择性确认选项用在连接初始化时,表示是否支持SACK技术。我们可以通过修改 /proc/sys/net/ipv4/tcp_sack 内核变量来启用或关闭选择性确认选项。

    6、kind=5,SACK实际工作的选项
      该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。

    7、该选项提供了较为准确的计算通信双方之间的回路时间(Round Trip Time,RTT)的方法,从而为TCP流量控制提供重要信息。我们可以通过修改 /proc/sys/net/ipv4/tcp_timestamps 内核变量来启用或关闭时间戳选项。

    三、现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?

       现代浏览器在与服务器建立了一个 TCP 连接后是否会在一个 HTTP 请求完成后断开?什么情况下会断开?

      在 HTTP/1.0 中,一个服务器在发送完一个 HTTP 响应后,会断开 TCP 链接。但是这样每次请求都会重新建立和断开 TCP 连接,代价过大。

      所以虽然标准中没有设定,某些服务器对 Connection: keep-alive 的 Header 进行了支持。

      意思是说,完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。

      这样的好处是连接可以被重新使用,之后发送 HTTP 请求的时候不需要重新建立 TCP 连接,以及如果维持连接,那么 SSL 的开销也可以避免,两张图片是我短时间内两次访问 https://www.github.com 的时间统计:

      头一次访问,有初始化连接和 SSL 开销

      初始化连接和 SSL 开销消失了,说明使用的是同一个 TCP 连接持久连接:既然维持 TCP 连接好处这么多,HTTP/1.1 就把 Connection 头写进标准,并且默认开启持久连接,除非请求中写明 Connection: close,那么浏览器和服务器之间是会维持一段时间的 TCP 连接,不会一个请求结束就断掉。所以第一个问题的答案是:默认情况下建立 TCP 连接不会断开,只有在请求报头中声明 Connection: close 才会在请求完成后关闭连接

    四、一个 TCP 连接可以对应几个 HTTP 请求?

      了解了第一个问题之后,其实这个问题已经有了答案,如果维持连接,一个 TCP 连接是可以发送多个 HTTP 请求的。

    五、一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?

      一个 TCP 连接中 HTTP 请求发送可以一起发送么(比如一起发三个请求,再三个响应一起接收)?

      HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。虽然 HTTP/1.1 规范中规定了 Pipelining(管线化机制) 来试图解决这个问题,但是这个功能在浏览器中默认是关闭的。先来看一下 Pipelining 是什么,RFC 2616 中规定了:

    1 A client that supports persistent connections MAY "pipeline" its requests (i.e., send multiple requests without waiting for each response).
    2  A server MUST send its responses to those requests in the same order that the requests were received. 
    3 一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。
    4 收到请求的服务器必须按照请求收到的顺序发送响应。

      至于标准为什么这么设定,我们可以大概推测一个原因:由于 HTTP/1.1 是个文本协议,同时返回的内容也并不能区分对应于哪个发送的请求,所以顺序必须维持一致。比如你向服务器发送了两个请求 GET/query?q=A 和 GET/query?q=B,服务器返回了两个结果,浏览器是没有办法根据响应结果来判断响应对应于哪一个请求的。

      Pipelining 这种设想看起来比较美好,但是在实践中会出现许多问题:

    • 一些代理服务器不能正确的处理 HTTP Pipelining。
    • 正确的流水线实现是复杂的。
    • Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。

      所以现代浏览器默认是不开启 HTTP Pipelining 的。但是,HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。至于 Multiplexing 具体怎么实现的就是另一个问题了。我们可以看一下使用 HTTP2 的效果。

      绿色是发起请求到请求返回的等待时间,蓝色是响应的下载时间,可以看到都是在同一个 Connection,并行完成的。

      所以这个问题也有了答案:在 HTTP/1.1 存在 Pipelining 技术可以完成这个多个请求同时发送,但是由于浏览器默认关闭,所以可以认为这是不可行的。在 HTTP2 中由于 Multiplexing 特点的存在,多个 HTTP 请求可以在同一个 TCP 连接中并行进行

      那么在 HTTP/1.1 时代,浏览器是如何提高页面加载效率的呢?主要有下面两点:

    • 维持和服务器已经建立的 TCP 连接,在同一连接上顺序处理多个请求。
    • 和服务器建立多个 TCP 连接。

    六、为什么有的时候刷新页面不需要重新建立 SSL 连接?

      在第一个问题的讨论中已经有答案了,TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的

    七、浏览器对同一 Host 建立 TCP 连接到数量有没有限制?

      假设我们还处在 HTTP/1.1 时代,那个时候没有多路传输,当浏览器拿到一个有几十张图片的网页该怎么办呢?

      肯定不能只开一个 TCP 连接顺序下载,那样用户肯定等的很难受,但是如果每个图片都开一个 TCP 连接发 HTTP 请求,那电脑或者服务器都可能受不了,要是有 1000 张图片的话总不能开 1000 个TCP 连接吧,你的电脑同意 NAT 也不一定会同意

      所以答案是:有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。https://developers.google.com/web/tools/chrome-devtools/network/issues#queued-or-stalled-requestsdevelopers.google.com

      那么回到最开始的问题,收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?

      如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。

      不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到

      如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。

      那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了

    八、参考文章

    https://mp.weixin.qq.com/s/Ue5FF9mwtccvQz9zL0Y4Ow

    本文来自博客园,作者:Mr-xxx,转载请注明原文链接:https://www.cnblogs.com/MrLiuZF/p/15055660.html

  • 相关阅读:
    前端构建工具gulp使用
    网页部分内容显示不全
    less简单入门
    jquery——移动端滚动条插件iScroll.js
    css3常用动画+动画库
    windows下nodejs环境配置
    jquery——滚动条插件jscroll.js
    工欲善其事必先利其器——dreamweaver
    jquery常用方法
    nodejs模块——http模块
  • 原文地址:https://www.cnblogs.com/MrLiuZF/p/15055660.html
Copyright © 2020-2023  润新知