计算机网络基础||从输入URL到打开页面到底发生了什么(待完善)
文章目录
- 从输入URL到打开页面到底发生了什么
- 1 应用层
- 1.1 解析URL
- 1.2 生成HTTP请求消息
- 1.3 向DNS服务器查web服务器的ip地址
- 1.3.1 通过解析器向dns服务器查询
- 1.3.2 解析器
- 1.4 委托协议栈发送消息
- 1.4.1 概览
- 1.4.2 应用程序委托收发数据的过程
- 2 传输层
- 2.1 协议栈概览
- ……
- 2.2 创建套接字
- 2.2.1 套接字是啥
- 2.2.2 调用组件的操作
- 2.3 连接服务器
- 2.3.1 连接啥意思
- 2.3.2 连接过程
- 2.4 收发数据
- 2.4.1 发数据
- 2.4.1.1 原理
- 2.4.1.2 重发超时
- 2.4.1.3 利用窗口提高速度
- 2.4.1.4 窗口控制与重发控制
- 2.4.1.5 流控制
- 2.4.1.6 拥堵控制--慢启动
- 2.4.2 收数据
- 2.5 从服务器断开并删除套接字
- 2.5.1 断开连接
- 2.3.2 删除套接字
- 3 网络层
- 3.1 IP网络包的传输方式
- 3.2 IP包收发操作
- 4 链路层
- 5 物理层
从输入URL到打开页面到底发生了什么
每个分层都有他的道理,这就跟JS代码加不加分号一样是很私人的事情,这里我为了方便理解就按照五层协议学习的
一张提纲挈领的图
几个问题
- 为什么网络协议要分层,这样的优缺点是什么
- 分层以后,每层有每层的协议,可以独立工作,一层的改变并不影响另一层
- 但是这样分层可能导致同样的逻辑在这层用一次,在那层用一次
- 分这么多层性能会差嘛
- 并不会,每一层层层封装最终也不过是多出来很少字节的数据,性能浪费没有想象的那么高
1 应用层
1.1 解析URL
URL (Uniform Resource Locator) 浏览网页差不多是从这一步开始,这里介绍下url的格式,这个链接的blog说的很详细,但是由于绝大多数网页都是HTTP/HTTPS协议,所以这一部分可以省略,同样,80端口号是默认的,一般也不用写,而由于http支持服务器将网页重定向,所以www也可以不用写,因此用户访问网页的时候只用键入一部分就可以了,比如https://www.mcppy.com
和mcppy.com
都可以进入同一个网站。
1.2 生成HTTP请求消息
解析完URL之后,我们就知道应该访问的目标在那里了,接下来浏览器会用HTTP协议来访问web服务器
HTTP协议:
他定义服务端与客户端交互消息的内容和步骤。
客户端发出一个request,客户端回应一个response
request报文主要包含两个部分
对什么(url)
进行怎么样的操作,这部分被称作方法,有人叫作http动词
这部分MDN有解释
整个http请求报文大概是这样的
- 第一行是请求行,包括三部分,用空格隔开
- 紧接着是报文头,是KV结构、属性名:属性值
- 待补充
response报文
待补充
1.3 向DNS服务器查web服务器的ip地址
- 因为ip地址是一串数字,很难记,所以就有了域名这个东西,但是知道ip地址才能传输数据,所以就有了DNS服务器,就跟小时候的电话本一样,知道域名可以查ip,知道ip可以查域名
- DNS是树状结构,能很快的查询到域名
1.3.1 通过解析器向dns服务器查询
向DNS服务器查web服务器的ip地址就是向dns服务器发消息,并接受服务器的响应消息。
我们电脑上有对应的dns客户端,叫做解析器,在操作系统的Socket库中,我们查ip是通过这个解析器向dns服务器发出查询,在编写浏览器等应用程序的时候,只要协商解析器程序名字+web服务器的域名就完成了对解析器的调用。调用解析器以后,是解析器向dns服务器发送潮汛消息,然后dns服务器返回响应消息,响应消息中包含查到的ip地址,解析器会取出ip地址,并将其写入浏览器知道的内存地址中。浏览器向web服务器发消息的时候,只要从该内存地址取出ip地址,并将它与http请求一起发给操作系统。
1.3.2 解析器
浏览器调用解析器的时候,浏览器本身的程序会被暂停,此时控制流程转移,当控制流畅转移到解析器以后,解析器会生成要发给dns服务器的请求,这个发送的操作是解析器委托给操作系统内部的协议栈来发送的,协议栈会通过网卡把消息发给dns服务器。
如果要访问的web服务器已经在dns服务器上注册的话,这个信息就能被找到,然后再被写入响应消息返回给协议栈,再经过解析器,写入web浏览器的指定的内存区域中。
向dns服务器发消息的时候,也要知道dns的ip地址,这个ip地址是被作为TCP/IP的一个设置事先写好了
1.4 委托协议栈发送消息
1.4.1 概览
知道ip地址以后就委托系统内部的协议栈去向这个目标ip发送HTTP请求了,
收发数据就是两台计算机之间连接了一条数据通道
做管道的关键是套接字,套接字就相当于管道两边的数据出入口,把套接字连起来就是管道了。
有以下四个阶段
- 创建套接字
- 建立通道
- 收发数据
- 断开连接
浏览器或者说是操作系统里面的Socket库并不能自己收发消息
应用程序是调用Socket库里面的组件来执行数据的收发操作,但是这四个步骤都是由操作系统的协议栈来实现的
协议栈是如何接到委托的?
应用程序调用Socket库中的应用组件,来委托协议栈,Socket就相当于一个桥梁的角色,不进行实质性操作,应用程序的委托内容会被原本的给协议栈。
1.4.2 应用程序委托收发数据的过程
应用程序通过按照一定顺序调用Socket库中特定的程序组件进行委托(这些组件就是api啦)
阶段 | 调用的组件 | 需要的参数 | 作用 |
---|---|---|---|
套接字阶段 | socket组件 | 创建套接字,返回描述符 | |
接通管道阶段 | connect组件 | 描述符,服务器ip地址,端口号 | 建立连接成功,协议栈会将对方的ip地址和端口号保存在套接字里 |
发送消息 | write组件 | 描述符和要发送的数据 | 服务器收到消息 |
客户端响应 | read组件 | 存放响应数据给应用程序的内存空间的缓冲区 | |
断开 | close组件 | 断开连接并且删除套接字 |
2 传输层
之前是应用程序委托协议栈发消息的过程,现在介绍协议栈如何处理并发送请求的
2.1 协议栈概览
协议栈的内部结构
上半部分 TCP/UDP协议
下半部分IP协议
ICPMP
ARP
……
2.2 创建套接字
2.2.1 套接字是啥
三个socket
- 首字母大写的表示库
- 小写的表示组件
- 套接字就表示套接字
套接字就是通信控制信息,记录控制通信操作的各种控制信息,协议栈根据这些信息判断下一步的行动
下图是在wibdows下用netstat
命令显示的套接字内容,创建套接字的时候会在这加一行控制信息,赋予即将开始通信状态,并进行通信的准备工作。
2.2.2 调用组件的操作
创建套接字时候会分配个内存空间,写入初始状态
2.3 连接服务器
2.3.1 连接啥意思
连接就是通信双方交换控制信息,(在套接字中记录这些信息)
连接有三个目的
- 套接字刚刚创立的时候,是空的,不知道数据该发给谁,浏览器知道端口和ip地址但是在调用socket api创建套接字的时候,这些信息没有传给协议栈。所以在连接的时候需要把这些信息告诉协议栈
- 服务器这里也会创建套接字,但是套接字不知道应该和谁通信,就连应用程序也不知道。所以需要客户端向服务端传达开始通信的请求
- 创建缓冲区
2.3.2 连接过程
从调用connect API 开始 ,这个会把服务器的ip地址和端口号给协议栈的TCP模块,然后服务器就开始和客户端交换控制信息了。过程如下
客户端创建TCP的header,到这里,客户端就知道要给谁发信息了
然后发送一个SYN包建立连接和请求,等待确认应答(是客户端给服务端发送者这个包)
- 这个是TCP委托IP模块发送网络包,网络包通过网络到达服务器,服务器的IP模块给服务器的TCP模块,这时候服务器的TCP模块根据header找到端口号对应的套接字,(就是找到与等待连接的服务端的套接字一样的被TCP包记录的套接字)
- 找到以后,套接字中会写入响应信息,把状态改为正在连接
- 上述操作完成后返回响应
(服务端给客户端)回应ACK包(针对SYN的确认应答),并且发送一个SYN包,请求建立连接
客户端回应ACK(针对SYN包)
- 如果连接成功,会向套接字写入服务器的信息,将状态改为连接完毕
为什么三次握手?
想象你在一个密室,你来确认旁边的房间有没有人,然后如果有人就建立一起商量怎么逃出去,怎么办
- 第一步,我先敲墙,试探看看有没有人
- 第二步,如果对方有人,就也敲下墙回应我
- 此时我知道两件事
- 对方有人
- 对方能听见我说话
- 这时对方知道几件事?
- 对方有人
- 但是不能知道对方能不能接收到我的信息
- 此时我知道两件事
- 所以第三步,我敲下墙,告诉对方我也能听见你敲墙
- finally,我们终于建立了连接,可以商量携手逃出密室了!
TCP头部格式
2.4 收发数据
2.4.1 发数据
2.4.1.1 原理
控制流从connect到达应用程序以后,接下来就到数据收发阶段了
发数据是调用write api开始的,协议栈收到数据以后怎么操作?
第一步:将HTTP请求交给协议栈
- 协议栈只负责发送数据,应用程序调用write的时候会指定发送数据的长度
- 协议栈不是一收到数据马上发出去,会将数据存在内部的发送缓冲区里,等待应用程序的下一段数据。,应用程序交给协议栈的数据长度是由应用长度本身决定的。如果协议栈已收到数据就发出去,这样会导致发出大量小包
- 积累多少数据才发送是下面几个要素
- 数据长度
- 协议栈有个MTU参数,它是一个网络包的最大长度(包含头部信息)
- MTU - header = MSS, 指的数据部分的最大长度
- 应用程序收到数据长度>=MSS的时候就可以发出去了
- 时间
- 程序每次等到数据>=MSS时候,会发生延迟,这种情况即使数据没有积攒狗也会发出去
- 这是操作系统和决定的
- 但是协议栈留下了些选项,比如(你的命后代填满缓冲区直接发送)
- 数据长度
第二步: 分包
如果信息很大,缓冲区被一下填满,就立即被拆分,每块数据会被放进单独的网络包里,MSS叫最大消息长度,理想是正好在ip数据包中不会被分片处理的最大数据长度。
这个MSS在三次握手的时候被计算出,两端主机发出连接请求的时候,会在TCP首部协商MSS,然后会在两者之间选个小的来用
第三步:ack确认
ACK里有
- 接收方窗口容量
- 期待的下一个编号
TCP拆分数据时,会给给个字节编号,发送数据时,会把算好的字节数写在TCP头部,发送数据的长度是整个数据包的长度假设header的长度
通过编号,接收方可以算出数据有没有遗漏,比如上次接受到1000字节,下次应该收到的应该是编号1001字节的包,如果不是就说明被遗漏了,如果没有遗漏,接受放会算出来一共接受了多少字节,写入TCP头部的ACK发给对方。
并且为了安全,ACK包并不是从1开始的,是随机的,这个是在上一步连接过程中(把SYN设为1的那一步)把这个序号的初始值告诉对方
双向传输,就是把刚刚的情形反过来
tcp这样确认数据有没有丢失,在收到ACK之前,发送过的包都在缓冲区呆着,如果没有返回ACK就重新发包
tcp还有好多控制方法 ,在下面介绍一部分
2.4.1.2 重发超时
前面说过,如果一段时间等不到ACK应答,(有两种情况,1. 数据包丢失 2. 数据包收到但是应答丢失)就会重新发包,那这个时间是多少,如果一直收不到ACK要无休止的发下去嘛?
这个时间因为网络环境不一样不能写死,所以tcp每次发包会记录往返时间和偏差,比往返时间+偏差大一点的是重发时间,在windows中是500ms,
如果重发超时得不到应答,就会再发,这个等待的时间会2倍,4倍指数级增长,达到一定次数就会关闭连接
2.4.1.3 利用窗口提高速度
如果每次发消息都要等到ACK才能执行下面的动作,那包的往返时间越长,通信性能越低
为了解决这个问题,TCP有了窗口这个概念
发送端主机在发送一个段以后不用一直等ACK,而是继续发,窗口大小就是无需等待应答还可以发数据的最大值,这个机制用了 大量的缓冲区。
滑动窗口
2.4.1.4 窗口控制与重发控制
情况一: 应答丢失
在这种情况下,只要收到了ACK700,就说明前面的数据都被收到了,这种叫做 累计确认
情况二: 报文丢失
高速重发,不已时间为标准,如果发送端连续接受同一个确认应答,就会对数据进行重发
但是有一个问题,客户端不知道要重发一个还是重发所有,它并不知道连续的这三个ACK是谁传回来的,所以就有了SACK方法。
会在TCP头部加上个SACK地图,这样就知道是哪一块数据没有收到了,就会准确的重发那一段
还有个D-SACK来告诉发送方哪些包被重复接收了
场景一,ACK丢包
在这个例子中,ACK包丢了,触发了重发机制,于是就发送了3000–3500的包
接受方发现重复接收了就返回个SACK = 3000-3500的包
场景二:网络延迟
- 发送方1000–1499丢失了,于是一直收到重复的ACK 1000报文,三次触发了高速重发
- 然后1000–1499的包终于被发送,所以接收方给发送方回了个SACK = 1000 – 1500但是此时ACK已经是3000了
- 所以发送方就知道是网络延时的问题了
所以D-SACK有三个好处
- 可以让发送方知道是不是网络延迟了
- 可以让发送方知道是发出去的包丢了还是ACK丢了
- 可以知道是不是有包被重复的接收了
2.4.1.5 流控制
如果发送方不考虑接收方的情况乱发数据,会导致接收方缓冲区溢出,处理不过来的情况,如果丢包又会触发重发机制,因此就有了流控制
数据的接收能力是由【接收方】的窗口大小决定的,这个窗口大小是【接收端】告诉【发送端】自己可以接收多大的数据,这个数据是动态的
如图,接收到3001以后的数据的时候,缓冲区满了,只能暂时停止发送数据,这时发送方会发一个窗口测探的包,如果接收到窗口更新才会继续发数据,要不然发送数据的过程会被中断。如果窗口更新的包丢了会影响通信,因此发送方会时不时的给接收方发送窗口探测的包
2.4.1.6 拥堵控制–慢启动
因为带宽的限制,如果通信刚开始发送大量的数据包,会导致网络拥堵,如果有很多主机通信,这时突然发个很大的数据包,会导致网络瘫痪,所以在通信一开始的时候,有个叫做慢启动的方法。对发送的数据量控制
tcp怎么进行拥堵控制的,这要结合tcp的工作机制,以及对三个问题的回答来看
- TCP必须使用端到端的拥堵控制而不是网络辅助的拥堵控制,因为ip层不提供网络控制的反馈,也就是说,TCP是通过发送端和接收端的数据包接收情况计算出来拥堵的,如果TCP发送方没感觉堵塞就加大数据传输速率,如果感到堵塞就降低发送的效率
- TCP包是怎么知道拥堵的
- TCP包是怎么控制发送的速度的
- TCP包感受到拥堵的时候,是采用什么样的算法调节发送速率呢
问题一:
- 把一个TCP发送方的丢包事件定义为要不然超时,要不然接收到来自接收方三个ACK(前面说过,丢包有两种情况,一个是ack丢,一个是数据包丢,分别对应时间和数据量,ack丢会引发超时,数据包丢会引起三个冗余的ACK)
- 当堵塞的时候,在这条路径上的一台(或者多台)路由器的缓存会溢出,这样会导致删除一个TCP包,删除这个TCP包会引起发送方的丢包事件,当出现丢包事件是,就认为是网络堵塞
问题二:
- 为了控制TCP发送方是如何限制流量的,我们引入一个概念,拥堵窗口(congestion window)在发送方一次发送的数据量要比cwnd和接收方的窗口大小(rwnd)小,
- 控制变量,如果不发生拥堵,而且TCP接收方的缓存足够大(与流量控制做对比),多大都能吃的下,还假设总有报文要发送,并且时延忽略不计的情况,因此粗略的说,速率等于CWND/RTT(往返时间)字节/秒,所以通过调节cwnd,发送方能控制发送数据的速率
问题三:算法
分为三个阶段
慢启动
拥堵避免
快速修复
(其中1.2是强制的)
大概说一下:
为了探测网络拥堵状况,我们有以下两个策略
先发个数据包测试一下,如果没有丢包,下次就发2MSS个,如果还是没有拥堵,下次就发三个,这样以此类推
大概是线性增长,这样的
一个一个发,太慢了,所以可能一开始发1个,下次发两个包,下次两个包分别加1,是4个,下下次是8个,这是假设没有网络拥堵的情况,但是这样指数增长太快了,很快就会拥堵,发生丢包,这时候大概就是指数增长
具体算法
慢启动:
- 一个TCP连接开始时,cwnd通常被设置为一个mss的较小值,在慢启动状态,cwnd的值以一个MSS开始,并且每当传输的报文被确定,就加一个MSS
- 那要何时结束呢?有几种答案
- 如果时超时丢包,tcp发送方将cwnd设置为1,并且重新开始慢启动,还记录了一个慢启动阈值(ssthresh),ssthresh = cwnd/2
- 与ssthresh关联,如果指数增长到慢启动阈值的时候,继续指数增长会有些鲁莽,所以,当cwnd = ssthresh时,会进入拥堵避免模式
- 如果监测到三个ACK包,TCP快速重传并进入快速恢复状态
拥堵避免:
这时候cwnd的值大概时上次遇到拥塞的一般,可能里拥塞不遥远,所以这时候不能指数增长,每一次RTT只将cwnd的值加一个MSS
如果MSS时1460字节,cwnd时14600字节,在一个RTT内发送10个报文段,假设每个报文段一个ACK,将增加十分之一MSS的拥塞窗口的长度
那什么时候结束拥堵避免呢?当然时出现丢包的时候
- 出现超时时:与慢启动一样,cwnd被设置为一个MSS
- 丢包事件出现时:ssthresh的值被更新为cwnd的一半,由三个ACK触发的时候,网络继续送发送方到接收方发送报文段,因此TCP对这种丢包的行为,相比于超时的丢包不那么剧烈。 tcp将cwnd的值减半,
计算机网络基础||从输入URL到打开页面到底发生了什么(待完善)相关推荐
- 地址栏输入URL到显示页面的过程
前言 从地址栏输入URL到显示页面都发生了什么?这是一道面试经常会考的面试题.那么下面我们就来探讨一下从你输入URL后到响应,都经历了哪些过程. 1.DNS解析 我们在用户PC中使用网页浏览器来访问外 ...
- 从浏览器地址栏输入url到显示页面的步骤
从浏览器地址栏输入url到显示页面的步骤(以HTTP为例) - 在浏览器地址栏输入URL - 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 - 如果资源未缓存,发起新请求 ...
- 在浏览器中输入URL按下回车键后发生了什么
在浏览器中输入URL按下回车键后发生了什么 [1]解析URL [2]DNS查询,解析域名,将域名解析为IP地址 [3]ARP广播,根据IP地址来解析MAC地址 [4]分别从应用层到传输层.网络层和数据 ...
- 浏览器输入地址可以打开页面,爬虫爬取不到页面的原因有可能是:<meta http-equiv=“refresh“ content=“0; url=“>是什么意思?
<meta http-equiv="refresh" content="0; url=">是什么意思? 页面定期刷新,如果加url的,则会重新定向到 ...
- 简略图解:输入 url 到出现页面,浏览器做了什么?
应该有很多前端开发人员都思考过这么一个问题:从输入 URL 到页面加载完成,中间都做发生了什么? 这个问题涉及的面非常广,每个涉及的点又很深入.从触屏/键盘如何到 CPU?CPU 如何到系统内核?如何 ...
- 【网络】浏览器输入URL到展示页面全过程(含互联网协议及HTTPS简介)
这里写自定义目录标题 前言 1.URL介绍 2.DNS查找 3.互联网协议 3.1 实体层 3.2 链路层 3.2.1 以太网协议 3.2.2 Mac地址 3.2.3 广播 3.3 网络层 3.3.1 ...
- 前端面试系列-输入url后全过程页面渲染机制DOM生成过程
文章目录 一.当输入url后,全过程 二.页面渲染机制 三.DOM 1.什么是 DOM 2.DOM 树如何生成 HTML 解析器 3.JavaScript 是如何影响 DOM 生成的 内嵌JavaSc ...
- 从浏览器输入URL到展示页面的全流程
从本地终端(如手机.电脑)访问一个网站,怎么处理请求并且加载出数据的.实际上考察的是计算机网络TCP/IP协议栈. 主要的得分项为TCP协议各层的描述.数据传送的封装和解包.一次页面包含多个TCP连接 ...
- 在浏览器中输入URL并回车后都发生了什么?
1.解析URL ________________________________________________________________________ 关于URL: URL(Universa ...
最新文章
- Spring Cloud(四) API网关Zuul
- Visual Studio Code 构建C/C++开发环境
- 阿里云服务器——centos7下安装MySQL,并且实现远程连接
- SQL Server – QP的另一个X射线
- 获取python脚本的返回值_Python多线程获取返回值代码实例
- Linux系统中提示/usr/bin/ld: cannot find -lxxx错误的通用解决方法
- 只需两步快速获取微信小程序源码
- Dubbo源码解析之SPI(一):扩展类的加载过程
- What is Drilldown configuration
- HTML页面布局适配不同分辨率
- mac 上查看字体文件的路径
- 水管工游戏——dfs
- openstack上 的云主机手动疏散案例
- 使用Unity制作VR全景图片清晰度的问题!!!
- 计算机专业必须知道的东西——C语言的发展
- 入门行人重识别 尝试跑(郑哲东 简单行人重识别代码到88%准确率)过程
- 武义县城区棚户区改造溪南区块安置房建设项目(标段一)电能管理系统的研究及应用
- 「题解」关于sizeof陷阱,无符号整形,变种水仙花数
- ET篇:做好准备工作并运行master分支的Demo
- 如何诊断Shopee店铺?记住这3个操作
热门文章
- iReaper:WebCast视频下载辅助工具
- java 热量图实现_安卓实现计步器,能够计算卡路里的消耗
- 社保系列6《账户划入交易》
- html font-family推荐,【CSS Trick】推荐 font-family 总写一个兜底字体
- c语言 读取摄像头图片分辨颜色,opencv摄像头捕获识别颜色
- BED(比特生态系统)白皮书中文翻译版
- 赛博朋克照入现实,Facebook大力布局AR硬件生态
- tomcat修改默认index.html,修改TOMCAT默认主页(示例代码)
- C语言检测数独是否合法,LintCode 判断数独是否合法
- execl 计算工作日
- 地址栏输入URL到显示页面的过程