精华内容
下载资源
问答
  • 这篇文章旨在尽可能详细的解释一个经典的面试问题“当你在浏览器地址栏键入’google.com’并按下enter键,会发生什么” 当你键盘上按下‘g’ 接下来的几节会解释所有有关键盘输入和操作系统中断的东西。但是...

    原文见 what happens when

    这篇文章旨在尽可能详细的解释一个经典的面试问题“当你在浏览器的地址栏键入’google.com’并按下enter键,会发生什么”

    当你在键盘上按下‘g’

    接下来的几节会解释所有有关键盘输入和操作系统中断的东西。但是之后发生的一大堆的事情是没有解释的。当你只是按下了’g’这个键,浏览器就会接收到这个事件,接下来浏览器的自动完成机制就会运行。根据你浏览器的算法以及你是否开启的隐私\无痕模式,网址栏的下拉框中会向你显示各种各样的建议。大多数算法会将历史搜索记录以及书签优先排在前面。反正你都要输入’google.com’,所以这些建议都不影响,但是在你最终输入完整的网址之前一大堆代码都在运行,并且每一次按下一个键这些建议都会改进。甚至在你输入网址之前就向你建议’google.com’。

    按下enter键

    让我们选择按下enter键,击中底部为起点。在这个时刻,被按下的键专用的电路被闭合(直接或电容式)。这使得少量电流流入键盘的逻辑电路,该逻辑电路会扫描每一个键开关的状态,消除开关快速断续闭合的电气噪声,并且将其转换为一个按键编码,(译者:每一个键对应一个编码,参考http://blog.csdn.net/zhaozhbcn/article/details/38852583),在这里Enter键对应的是13。然后主机键盘控制器负责将按键编码再编码成计算机能理解的码字并传输给计算机。现在一般通过通用串行总线(USB)或者蓝牙连接,以前通过PS/2 或者 ADB连接。

    如果使用的是USB键盘

    • 键盘的USB电路由计算机的USB主控制器上的引脚1提供的5V电源供电。
    • 产生的按键编码由内部键盘电路存储器存储在一个叫“终端”的寄存器中。
    • 主机键盘控制器每10ms(由键盘声明的最小时间)获取“终端”中的值,所以它能够得到存放在寄存器中的按键编码。
    • 这个编码由SIE(串行接口引擎)根据低级USB协议转化为USB数据包。
    • 这些数据包以不同的电子信号以最高速率1.5M/s从(中间的两个)D+和D-引脚发送,因为HID(人机接口设备)总是被声明为“低速度设备”(usb2.0规格)
    • 这个串行信号被计算机的主机控制器编码,由计算机的HID通用键盘设备驱动产生中断。这个键盘的编码便传入操作系统的硬件抽象层。

    如果使用的是虚拟(触屏设备)键盘

    • 当用户将手指放在现代的电容式触摸屏上时,会有少量的电流转移到手指上。这形成了一个通过导电层的静电场的电路,并在触屏的位置产生一个电位差。屏幕控制器产生一个中断来报告按键的坐标。
    • 然后移动操作系统在其GUI元素之一(现在是虚拟键盘应用程序按钮)中通知当前关注的应用程序的按键事件。
    • 虚拟键盘产生软中断,发送一个按下键盘的消息给操作系统。
    • 操作系统通知当前关注的这个应发生的这个按键事件。

    中断の焰(非USB键盘)

    (译者注:实在不知道怎么翻译这个小标题:interrupt fires)
    键盘发送信号到其中断请求队列,一类中断请求由中断控制器映射到一个中断向量。CPU使用IDT(Interrupt Descripter Table,中断描述符表)将一个中断向量映射到由内核提供的处理该中断的程序(interrupt handlers)。当一个中断到达,CPU检索中断描述符表,找到对应的中断向量,运行其处理程序。此时,内核登场了。

    (Windows上)WM_KEYDOWN信息被发送给应用程序

    HID(人机交互设备)传输系统将按下键盘这个事件传给KBDHID.sys驱动,这个驱动会将HID用法转化成扫描码。在这里这个扫描码是VK_RETURN(0x0D)。KBDHID.sys驱动和KBDCLASS.sys(keyboard class driver)进行接合。这个驱动文件负责以一种安全的方式处理所有的键盘和键区输入。然后它调用Win32K.sys(在通过可能安装的第三方键盘过滤器传递消息之后)。这些都发生在内核态。

    Win32K.sys 通过 GetForegroundWindow() API明确那个窗口处于活跃(active)状态。这个API提供了浏览器地址栏的窗口句柄。Windows消息泵调用SendMessage(hWnd, WM_KEYDOWN, VK_RETURN, lParam)lParam是位掩码用于指示按键更多的信息:重复次数(这里是0),真正的扫描码(可依赖于原始设备制造商,但通常在VK_RETURN情况下不是),是否是扩展的键(如alt, shift, ctrl)被按下(在这里不是),以及其他一些状态。

    Windows的SendMessage API是一个简单的函数,它将消息添加到特定的窗口句柄(hWnd)的消息队列中去。然后,调用分配给hWnd的主要的消息处理函数(叫做WindowProc)来处理这个消息队列中的每一条消息。

    活动的窗口(hWnd)实际上是一个编辑控件,在这种情况下WindowProc具有WM_KEYDOWN消息的消息处理程序。 此代码在传递给SendMessage(wParam)的第三个参数中查找,因为它是VK_RETURN,所以知道用户已经按下了ENTER键。

    (MAC OS上)NSEvent会发送给应用程序

    中断信号触发在I/O Kit kext 键盘驱动程序中的中断事件。驱动程序将信号转化为按键编码传送给OS X 的WindowServer进程。WindowServer通过其Mach端口将事件分派到任何适当的(例如活跃的或监听中的)应用程序中,并将其放置到事件队列中。事件可以被有着足够权限的线程通过调用mach_ipc_dispatch函数从事件队列中读出。这通常通过NSEventType KeyDownNSEvent发生,并由NSApplication主事件循环处理。

    (在GNU/Linux上)Xorg服务程序监听键盘编码

    当使用图形化界面X server时,X会使用通用事件驱动程序evdev来获取按键事件。然后使用X server特定的键盘映射和规则将键码重新映射到扫描码。扫描码的映射完成之后X server将字符发送给window manager(比如,DWM, metacity, i3, etc),window manager再把字符发送给指定的窗口。这个窗口的图形化API接收到这个字符在正确的获得焦点的地方以合适的字体符号显示出来。

    解析URL

    现在浏览器有了包含在url中的如下信息:

    • 协议 ‘http’
      使用的是超文本传输协议
    • 资源 ‘/’
      检索根目录

    判断内容是URL还是搜索条目

    当并非协议或者有效域名的内容提供给浏览器进行处理的时候,地址栏中的内容就传送给浏览器默认的搜索引擎。很多情况下URL有特殊的文本块连接在其后面告诉搜索引擎它来自哪一个浏览器地址栏。

    在主机名中转换非ASCII的Unicode字符

    • 浏览器检查主机名中的字符是否在a-z,A-Z, 0-9, -, or .
    • 因为这次输的是 google.com所以没什么,但是如果有的话,浏览器会将Punycode编码应用到URL的主机部分。

    (译者注:早期的DNS(Domain Name System)是只支持英文域名解析。在IDNs(国际化域名Internationalized Domain Names)推出以后,为了保证兼容以前的DNS,所以,对IDNs进行punycode转码,转码后的punycode就由26个字母+10个数字,还有“-”组成。)

    检查HSTS列表

    • 浏览器检查其“预加载的HSTS(HTTP Strict Transport Security,HTTP严格传输安全)”列表。这是一个要求只能通过HTTPS连接的网址的列表。
    • 如果这个网址在这个列表上,那么浏览器就会使用HTTPS而不是HTTP发送它的请求。否则,初始化连接请求就是使用HTTP发送。(注意,网站仍然可以使用HSTS策略,而不需要在HSTS列表中。 用户向网站发送的第一个HTTP请求将会收到一个响应,请求用户只发送HTTPS请求。 但是,这个单一的HTTP请求可能会使用户容易遭受“降级攻击”,这就是为什么HSTS列表被包含在现代Web浏览器中的原因。)

    DNS查询

    • 浏览器先检查该域名是否在其缓存中。(Chrome浏览器的DNS缓存可以在chrome://net-internals/#dns 看到)。
    • 如果缓存中没有,它就调用gethostbyname库函数(根据具体的操作系统有所差别)进行查询。
    • gethostbyname在使用DNS解析主机名之前会检查本地host文件(位置根据具体的操作系统有差别)看是否能够解析主机名。
    • 如果gethostbyname既没有缓存改主机名,在host文件中也没有找到,则发送请求到网络堆栈中配置的DNS服务器,通常来说是本地服务器或者ISP(因特网服务提供商)的缓存DNS服务器。
    • 如果DNS服务器在同一个子网上,那么网络库将为DNS服务器执行ARP 过程
    • 如果DNS服务器位于不同的子网上,则网络库将为使用默认网关IP执行ARP 过程

    APR过程

    要发送一个ARP(Address Resolution Protocol,地址解析协议)广播,网络堆栈库需要一个IP地址用于查询。它也需要知道用来发送这个ARP广播的接口的MAC地址。

    首先检查APR缓存是否包含目标IP地址,如果是,则返回结果:目标 IP 地址= 对应的MAC。

    如果这个条目不在缓存中:

    • 查询路由表看目标PI地址是否在路由器表的某个子网内,如果是,这个库函数就会使用和那个子网相关联的接口,如果不是,则使用和默认网关相关联的接口。
    • 所选择的网络接口的MAC地址呗查询到。
    • 网络库发送一个第二层的请求(数据链路层,根据OSI七层模型)的ARP请求。

    ARP Request:

    Sender MAC: interface:mac:address:here
    Sender IP: interface.ip.goes.here
    Target MAC: FF:FF:FF:FF:FF:FF (Broadcast)
    Target IP: target.ip.goes.here

    根据计算机和路由器之间的硬件类型:

    直接相连:

    • 如果计算机和路由器直接相连,路由器返回一个ARP Reply的响应(见下面)。

    集线器:

    • 如果计算机和一个集线器相连,这个集线器会广播这个ARP请求给其他的端口。如果集线器和某个路由器相连,则路由器返回一个ARP Reply的响应(见下面)。

    交换机:

    • 如果计算机是和一个交换机相连,交换机检查它本地CAM/MAC表来看哪一个端口有正在查询的MAC地址。如果交换机没有这个MAC地址的条目,它将广播给其它端口。
    • 如果交换机本地CAM/MAC表有这个条目,它会发送ARP请求到有这个MAC地址的端口。
    • 如果路由器正好连接在了这个端口,则路由器返回一个ARP Reply的响应(见下面)。

    ARP Reply:

    Sender MAC: target:mac:address:here
    Sender IP: target.ip.goes.here
    Target MAC: interface:mac:address:here
    Target IP: interface.ip.goes.here

    现在网络库函数有了不管是DNS服务器或者可以进行DNS解析进行的默认网关的IP地址了。

    • 53号端口用于发送一个UDP请求到DNS服务器。(如果响应的数据包很大,则会使用tcp协议代替)。
    • 如果本地/ISP 的DNS服务器无法查询到该域名,则会根据DNS服务器列表递归查询,直到查找到起始授权机构。如果查询到了,则返回该结果。

    打开一个套接字

    一旦浏览器得到了目标服务器的IP地址,它会使用它并且加上一个端口号,端口号根据url中使用的协议有所不同,(http是80端口,而https是443端口),然后调用一个系统库函数socket,请求一个TCP套接字,AF_INET/AF_INET6SOCK_STREAM

    • 这个请求首先发送给传输层,TCP数据包分段在这个层生成,目的端口被加在tcp协议头部,从内核的动态端口范围中选择一个源端口号(Linux中叫做ip_local_port_range )
    • tcp分段被发送往网络层,在这一层加上IP头部。再给每一帧加上机器网卡的MAC地址以及网关的MAC地址,就像前面一样,如果内核不知道网关的MAC地址,就需要广播ARP请求得到MAC地址。

    在这个时刻数据包就准备好通过一下几种网络进行传输了:

    • 以太网
    • WIFI
    • 蜂窝数据通信网络

    对大多数家庭或者小型公司互联网连接来说,这个数据包会通过你的电脑,可能通过一个本地网络,然后通过一个调制解调器(俗称的‘猫’),将数字信号0和1转换成模拟信号以便在电话、电缆或者无线电话连接中传输。在这个连接的另一端,有另一台调制解调器将模拟信号转化为数字信号可以在下一个网络节点中进行处理,在这些节点,这个数据包的源主机和目的主机的地址可以得到进一步的分析。

    大多数大型企业和一些较新的住宅连接将具有光纤或直接以太网连接,在这种情况下数据保持数字化并直接传递到下一个网络节点进行处理。

    最终,数据包将到达管理本地子网的路由器。从这里,它会继续跨越自制系统的边界路由器以及其他自治系统,最终到达目的服务器。在这条路上的每一个路由器都会提取IP头部中的目的地址将其送到合适的下一跳,这个包的生存时间每经过一跳便会减少1,如果TTL字段达到零,或者当前路由器的队列中没有空间(可能由于网络拥塞),数据包将被丢弃。

    这样的发送以及接受过程会在以下的TCP连接中发生很多次:
    (译者注:TCP三次握手过程,TCP头部见下图)
    TCP头部格式

    • 客户端选择一个初始化序列号(ISN)填入序列号字段并且发送一个SYN标志位置为1的TCP数据包指明他设置了初始化序列号。
    • 服务器收到SYN包并且服务器也处在一个合适的状态(译者:大概就是服务器有资源可以提供吧)
      • 服务器选择它的初始序列号
      • 置SYN标志位置为1
      • 复制客户端的序列号并加1到ACK字段,将ACK标志位置1表明它确认收到第一个数据包
    • 客户端发送一个数据包确认连接
      • 将之前发送的那个序列号加1
      • 将收到的ACK号加1(译者:存疑)
      • 将ACK标志位置1

    (根据译者所知这个步骤应该是,客户端接受到服务器的ACK包,要进行确认则将服务器的序列号加1填入ACK字段,将ACK标志位置1,序列号是之前发送的那个SYN包的序列号加1,将数据包发送给服务器端)

    这个时候连接建立完成。

    • 数据按以下方式传输
      • 如果哪一方传输了N字节的数据,将序列号加上N
      • 如果另一方要确认收到了一个数据包或者若干个数据包,他发送的ACK包中的ACK号需要等于最后收到那个数据包的序列号。
    • 关闭连接
      • 关闭者发送一个FIN包
      • 另一发送ACK包响应这个FIN包,并发送自己的FIN包
      • 关闭者发送ACK包确认上一个FIN包

    TLS握手

    • 客户端向服务器发送ClientHello消息,该消息包括TLS版本号,加密算法套件,以及可用的压缩方法。
    • 服务器返回一个ServerHello消息,内容包括TLS版本号,选择的加密方法和压缩方法,以及服务器的由CA(认证中心)认证的公钥证书。证书包含一个公钥,客户端将使用该公钥来加密握手的其余部分,直到协商好对称密钥为止。
    • 客户端对比它所信任的CA的列表来验证服务器的数字证书。如果可以建立起基于这个CA的信任,客户端产生一串伪随机字节,并用服务器的公钥进行加密。这些随机字节将用于决定最后的对称密钥。
    • 服务器端使用自己的私钥解密消息得到伪随机字节,并使用它们生成对称主密钥。
    • 客户端发送Finished消息给服务器,使用对称密码加密了这一次的传输的哈希值。
    • 服务器根据消息生成了自己的hash值,并对比客户端发送的hash值看是否相等。如果相等,它将用对称密钥加密自己的Finished消息发送给客户端。
    • 从现在开始TLS回话将使用两者协商好的对称密钥进行加密HTTP数据。

    HTTP 协议

    如果所使用的Web浏览器是由Google编写的,则不会发送HTTP请求来检索这个页面,而是会发送一个请求,尝试与服务器协商从HTTP到SPDY协议的“升级”。

    (译者注:SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。)

    如果客户端使用HTTP协议,并不支持SPDY协议,它会发送一个如下形式的请求给服务器:

    GET / HTTP/1.1
    Host: google.com
    Connection: close
    [other headers]

    其中[other headers]指的是按照HTTP规范格式化的一系列以冒号分隔的键值对,并由单个新行分隔。(这假定正在使用的Web浏览器没有任何违反HTTP规范的错误。 这还假定Web浏览器使用HTTP / 1.1,否则它可能不包含请求中的Host头部,GET请求中指定的版本将为HTTP / 1.0HTTP / 0.9。)

    HTTP/1.1为发送者定义了“关闭”连接选项,发出信号表明在完成这个响应之后连接将关闭。例如:

    Connection: close

    不支持持久连接的HTTP/1.1 应用程序必须在每条消息后面包含关闭连接选项。

    在发送了请求和头部之后,浏览器发送一行新的空行给服务器表示自己的请求内容发送完成。

    服务器返回一个表示请求状态的响应码,并用以下格式的响应进行响应:

    200 OK
    [response headers]

    接着发送一个新的空行。在发送装有www.google.com的HTML内容。这时服务器或者关闭连接,或者按照客户端发送的请求头部中要求的那样,保持连接以便利用这次连接进行更多的请求。

    如果由浏览器发送的头部中包含足够的信息可以让web服务器判断自从上次检索(即,如果网页浏览器包括ETag头部)以来web浏览器缓存的文件的版本是否未被修改, 可以改为以表格的请求回应:

    304 Not Modified
    [response headers]

    然后服务器就不发送网页内容了,web浏览器会自己就会从自己的缓存中检索HTML内容。

    在解析HTML之后,网页浏览器(和服务器)为HTML页面引用的每个资源(图像,CSS,favicon.ico等)重复这个过程,除了GET / HTTP / 1.1之外,请求将是GET/$(相对于www.google.com的网址)HTTP / 1.1

    如果HTML引用的是别的域名的资源而不是www.google.com,浏览器回到解析域名,重复所有步骤。请求中的Host头部也会被设置为其他合适的服务器名而不是goole.com

    HTTP 服务器请求处理

    HTTPD(HTTP 守护进程)服务器在服务器端专门处理请求/响应。最常见的HTTPD服务器是用于Linux操作系统的Apache 或者 nginx ,以及用于Windows系统的IIS。

    • HTTPD 接受请求。
    • 服务器将请求分解为一下参数:
      • HTTP请求方法:GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, 或者 TRACE其中的一种。在url直接输入地址栏的情况下,方法是GET
      • 域名,在这里是goole.com。
      • 请求路径或者页面,在这里是 / (在没有指明路径或者页面的情况下,/是默认路径)
    • 服务器验证是否配置了google.com 对应的虚拟主机。
    • 服务器验证google.com是否接受GET请求。
    • 服务器验证客户端是否可以使用该请求方法(通过IP地址,认证等)
    • 如果服务器安装了重写模块,(比如Apache的mod_rewrite 或者 IIS的 URL Rewrite),服务器会先将请求和其中的配置规则进行匹配,如果匹配规则找到了,服务器使用这个规则重写这条请求。
    • 服务器获取与请求对应的内容,在这里它会回到到索引文件,因为/是根目录,(有的情况会重写,但这是最普遍的方法)。
    • 服务器根据处理程序解析文件。如果Google运行在PHP上,服务器根据PHP解释这个索引文件,发送结果给客户端。

    浏览器背后

    一旦服务器向浏览器提供了这些资源(HTML, CSS, JS, images, 等),浏览器经历如下几步:

    • 解析 - HTML,CSS,JS
    • 渲染 - 构建DOM树→渲染树→渲染树的布局→绘制渲染树

    浏览器

    浏览器的功能是通过从服务器那请求资源以及展示在浏览器窗口中来展现你所选择的资源。资源通常是HTML文件,也有可能是PDF文件,图片或者其他类型的内容。这些资源的位置通过用户使用URI(Uniform Resource Identifier,统一资源标识符)指明。

    浏览器解释和显示HTML文件的方式由HTML和CSS规范中指定。这些规范由为W3C组织(World Wide Web 联盟)维护,W3C是web的标准组织。

    浏览器用户界面有很多共同之处。 常见的用户界面元素包括:

    • 插入URI的地址栏
    • 回退和前进的按钮
    • 书签选项
    • 刷新和停止按钮用于刷新和停止对当前文档的加载
    • Home按钮,可以返回Home页面

    浏览器高级结构

    浏览器的组件有:

    • 用户界面:用户界面包括地址栏,后退/前进按钮,书签菜单等。除了可以看到你请求的那个页面的窗口,浏览器的每个部分都有所显示。
    • 浏览器引擎:浏览器引擎编排用户界面和渲染引擎之间的行为。
    • 渲染引擎:渲染引擎负责展示请求的页面内容。比如如果请求的内容是HTML,渲染引擎解析HTML和CSS,将解析的内容展现在屏幕上。
    • 网络:网络组件处理诸如HTTP请求之类的网络调用,在独立于平台的接口后面,根据不同平台,有着不同的实现。
    • UI后端:UI后端用于绘制组合框和窗口等基本小部件。 这个后端公开了一个不是特定于平台的通用接口。
    • JavaScript引擎:用于解析并执行JS脚本。
    • 数据存储:数据存储是一个持久层。浏览器需要在本地保存所有类型的数据,比如cookies。浏览器也支持各种存储机制如:localStorage, IndexedDB, WebSQL 以及 FileSystem。

    HTML解析

    渲染引擎从网络层得到请求文档的内容开始。这通常在8kB大小的chunk中完成。

    HTML解析器的主要工作是将HTML标记解析为解析树。

    这个输出的树(解析树)是一棵DOM元素以及属性节点的树。DOM是Document Object Model(文档对象模型)的简写。它是HTML文档的对象表示,以及HTML元素对外面的世界如JS的接口。这棵树的跟是“Document”对象。在通过脚本进行任何操作之前,DOM与标记之间几乎有一对一的关系。

    解析算法

    HTML不可以用常规的自顶向下或者字底向上的解析器解析。

    原因如下:

    • 语言的宽容性。
    • 浏览器具有传统的容错能力来支持众所周知的无效HTML案例。
    • 解析过程是可重入的。对于其他语言,在解析过程中源代码不会改变,但在HTML中,动态代码(如包含document.write()调用的脚本元素)可以添加额外的标记,因此解析过程实际上会修改输入。

    因为无法使用常规的解析技术,浏览器使用自定义的解析器来解析HTML代码。解析算法在HTML5规范中有详细描述。

    算法包含两个阶段:标记化和构建树

    当解析完成之后的行为

    浏览器获取这个页面引用的额外的资源((CSS, images, JavaScript files, 等)。

    在这一阶段,浏览器将文档标记为交互式,并开始解析处于“延迟”模式的脚本:在解析文档之后应执行的脚本。 文档状态设置为“完成”,并触发“加载”事件。

    注意:在HTML页面中不存在无效的语法。浏览器会修复无效的内容并继续。

    CSS解释

    • 使用‘CSS词法和语法’解析CSS文件,<style>标签内容,style属性值。
    • 每一个CSS文件被解析成StyleSheet对象,每个对象都包含具有选择器和对象的CSS语法的CSS规则。
    • 当使用特定的解析器生成器时,CSS解析器可以是自顶向下或者自下而上的。

    页面渲染

    • 遍历DOM节点生成帧树或者渲染树,并为每一个节点计算CSS样式的值。
    • 通过将子节点的首选宽度和节点的水平边界,边界和填充值相加,计算“框架树”中每个节点的首选宽度。
    • 通过将每个节点的可用宽度分配给子节点,从上到下计算每个节点的实际宽度。
    • 通过应用文本换行和总计子节点高度和节点的边界,边界和填充来计算每个节点的高度。
    • 使用上面的计算结果计算每个节点的坐标。
    • 如果元素是floated,位置是absolutely或者relatively,更或者使用了其他更复杂的特性,那么渲染阶段会有更复杂的步骤。详情参见 http://dev.w3.org/csswg/css2/ http://www.w3.org/Style/CSS/current-work
    • 创建图层来描述页面的哪些部分可以作为一组进行动画,而不用重新栅格化。 每个帧/渲染对象被分配给一个图层。
    • 给页面的每一层分配纹理。
    • 遍历每个图层的帧/渲染对象,并为其各自的图层执行绘图命令。 这可能会被CPU光栅化,或者使用D2D / SkiaGL直接在GPU上绘制。
    • 上述所有步骤可能会重利用上一次页面被渲染时计算的结果,这样的话额外的改变会要求做少量的工作。
    • 页面图层被发送到合成过程,在那里它们与其他可见内容(如浏览器镶边,iframe和附加面板)的图层相结合。
    • 计算最终图层位置,并通过Direct3D / OpenGL发布复合命令。 GPU命令缓冲区被刷新到GPU进行异步渲染,帧被发送到窗口服务器。

    GPU渲染

    • 在渲染过程中,图形计算层也可以使用通用CPU或图形处理器GPU。
    • 在使用GPU进行图形渲染计算时,图形软件层会将任务切割成多个部分,因此它可以利用GPU强大的并行处理能力来进行渲染过程所需的浮点计算。

    Windows 服务器

    后期渲染和用户引发的执行

    渲染完成之后,浏览器将执行JS代码可能是因为一些定时机制(比如一个Google涂鸦动画),或者是用户的交互(在搜索框中输入请求并受到建议)。插件或者Flash也有可能执行,尽管不是在这次的Google主页上。脚本也会造成额外的网络请求,也会修改这个页面或者它的页面布局,也会引发其他的页面渲染和绘图过程。

    展开全文
  • 当我们在浏览器地址栏输入www.cnblogs.com,然后回车,回车到看到页面到底发生了什么呢? 域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 -...

     

    当我们在浏览器的地址栏输入 www.cnblogs.com ,然后回车,回车到看到页面到底发生了什么呢?

    域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 --> 服务器响应http请求,浏览器得到html代码 --> 浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

    一、域名解析

    首先Chrome浏览器会解析www.cnblogs.com这个域名对应的IP地址。怎么解析到对应的IP地址?

    1. Chrome浏览器会首先搜索浏览器的DNS缓存(缓存时间比较短,TTL默认是1000,且只能容纳1000条缓存),看自身的缓存中是否有www.cnblogs.com对应的条目,而且没有过期,如果有且没有过期则解析到此结束。

      注:我们怎么查看浏览器的DNS缓存?可以使用 chrome://net-internals/#dns 来进行查看
    2. 如果浏览器自身的缓存里面没有找到对应的条目,那么Chrome会搜索操作系统的DNS缓存,如果找到且没有过期则停止搜索解析到此结束。

      注:怎么查看操作系统的DNS缓存,以Windows系统为例,可以在命令行下使用 ipconfig /displaydns 来进行查看
    3. 如果在Windows系统的DNS缓存也没有找到,那么尝试读取hosts文件(位于C:\Windows\System32\drivers\etc),看看这里面有没有该域名对应的IP地址,如果有则解析成功。
    4. 如果在hosts文件中也没有找到对应的条目,浏览器就会发起一个DNS的系统调用,就会向本地配置的首选DNS服务器(一般是电信运营商提供的,也可以使用像Google提供的DNS服务器)发起域名解析请求(通过的是UDP协议向DNS的53端口发起请求,这个请求是递归的请求,也就是运营商的DNS服务器必须得提供给我们该域名的IP地址),运营商的DNS服务器首先查找自身的缓存,找到对应的条目,且没有过期,则解析成功。如果没有找到对应的条目,则有运营商的DNS代我们的浏览器发起迭代DNS解析请求,它首先是会找根域的DNS的IP地址(这个DNS服务器都内置13台根域的DNS的IP地址),找打根域的DNS地址,就会向其发起请求(请问www.cnblogs.com这个域名的IP地址是多少啊?),根域发现这是一个顶级域com域的一个域名,于是就告诉运营商的DNS我不知道这个域名的IP地址,但是我知道com域的IP地址,你去找它去,于是运营商的DNS就得到了com域的IP地址,又向com域的IP地址发起了请求(请问www.cnblogs.com这个域名的IP地址是多少?),com域这台服务器告诉运营商的DNS我不知道www.cnblogs.com这个域名的IP地址,但是我知道www.cnblogs.com这个域的DNS地址,你去找它去,于是运营商的DNS又向www.cnblogs.com这个域名的DNS地址(这个一般就是由域名注册商提供的,像万网,新网等)发起请求(请问www.cnblogs.com这个域名的IP地址是多少?),这个时候cnblogs.com域的DNS服务器一查,果真在我这里,于是就把找到的结果发送给运营商的DNS服务器,这个时候运营商的DNS服务器就拿到了www.cnblogs.com这个域名对应的IP地址,并返回给Windows系统内核,内核又把结果返回给浏览器,终于浏览器拿到了www.cnblogs.com对应的IP地址,该进行一步的动作了。

    DNS递归解析图如下所示:
    DNS递归解析图
    DNS迭代解析图如下所示:
    DNS迭代解析图
    注:一般情况下是不会进行以下步骤的,如果经过以上的4个步骤,还没有解析成功,那么会进行如下步骤:

    1. 操作系统就会查找NetBIOS name Cache(NetBIOS名称缓存,就存在客户端电脑中的),那这个缓存有什么东西呢?凡是最近一段时间内和我成功通讯的计算机的计算机名和Ip地址,就都会存在这个缓存里面。什么情况下该步能解析成功呢?就是该名称正好是几分钟前和我成功通信过,那么这一步就可以成功解析。

    2. 如果第5步也没有成功,那会查询WINS 服务器(是NETBIOS名称和IP地址对应的服务器)

    3. 如果第6步也没有查询成功,那么客户端就要进行广播查找

    4. 如果第7步也没有成功,那么客户端就读取LMHOSTS文件(和HOSTS文件同一个目录下,写法也一样)

    如果第八步还没有解析成功,那么这次解析失败,那就无法跟目标计算机进行通信。只要这八步中有一步可以解析成功,那就可以成功和目标计算机进行通信。

    二、发起TCP的3次握手

    拿到域名对应的IP地址之后,User-Agent(一般是指浏览器)会以一个随机端口(1024 < 端口 < 65535)向服务器的WEB程序(常用的有tomcat,nginx等)80端口发起TCP的连接请求。这个连接请求(原始的http请求经过TCP/IP4层模型的层层封包)到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈(用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。如下图:

    TCP三次握手

    注:TCP三次握手详解

    三、建立TCP连接后发起http请求

    HTTP请求报文的方法是get方式,如果浏览器存储了该域名下的Cookies,那么会把Cookies放入HTTP请求头里发给服务器。

    下面是Chrome发起的http请求报文头部信息:

    GET / HTTP/1.1
    Host: www.cnblogs.com
    Connection: keep-alive
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Referer: http://www.cnblogs.com/wupeixuan/
    Accept-Encoding: gzip, deflate, br
    Accept-Language: zh-CN,zh;q=0.9

    四、服务器端响应http请求,浏览器得到html代码

    服务器端WEB程序接收到http请求以后,就开始处理该请求,处理之后就返回给浏览器html文件。

    用Chrome浏览器看到的响应头信息:

    HTTP/1.1 200 OK
    Date: Sun, 08 Apr 2018 10:51:00 GMT
    Content-Type: text/html; charset=utf-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Vary: Accept-Encoding
    Cache-Control: public, max-age=29
    Expires: Sun, 08 Apr 2018 10:51:29 GMT
    Last-Modified: Sun, 08 Apr 2018 10:50:59 GMT
    X-UA-Compatible: IE=10
    Content-Encoding: gzip

    五、浏览器解析html代码,并请求html代码中的资源

    浏览器拿到index.html文件后,就开始解析其中的html代码,遇到js/css/image等静态资源时,就向服务器端去请求下载(会使用多线程下载,每个浏览器的线程数不一样),这个时候就用上keep-alive特性了,建立一次HTTP连接,可以请求多个资源,下载资源的顺序就是按照代码里的顺序,但是由于每个资源大小不一样,而浏览器又多线程请求请求资源,所以从下图看出,这里显示的顺序并不一定是代码里面的顺序。

    浏览器在请求静态资源时(在未过期的情况下),向服务器端发起一个http请求(询问自从上一次修改时间到现在有没有对资源进行修改),如果服务器端返回304状态码(告诉浏览器服务器端没有修改),那么浏览器会直接读取本地的该资源的缓存文件。
    image

    六、浏览器对页面进行渲染呈现给用户

    最后,Chrome浏览器利用自己内部的工作机制,把请求到的静态资源和html代码进行渲染,渲染之后呈现给用户。

     

    转自:https://www.cnblogs.com/wupeixuan/p/8747918.html

    展开全文
  • 对于Struts2、Spring3、Hibernate3集成使用的项目来说,对用户请求的控制是非常重要的,有些操作...①浏览器地址栏中直接输入url访问action的问题 ②过滤不想被拦截的方法 例如对于如下链接: http://loc
    对于Struts2、Spring3、Hibernate3集成使用的项目来说,对用户请求的控制是非常重要的,有些操作需要用户登录后才能执行。如果不做任何限制,则action可以直接在浏览器中输入action地址来执行相应的action.本文主要解决的就是
    

    ①浏览器地址栏中直接输入url访问action的问题

    ②过滤不想被拦截的方法

    例如对于如下链接:

    1. http://localhost:8080/absSys/delete.action?id=1

    直接在浏览器中提交上述地址,delete操作依然能执行!因此,必须对用户提交的请求进行拦截处理,如果用户没有登录,则跳转至登录页面。

    一、浏览器地址栏中直接输入url访问action的问题

    Struts2提供了拦截器,我们编写自己的拦截器的时候,只需要继承抽象类AbstractInterceptor,然后override intercept()方法就可以了

    1. import java.util.Map;
    2. import com.opensymphony.xwork2.ActionContext;
    3. import com.opensymphony.xwork2.ActionInvocation;
    4. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    5. public class LoginInterceptor extends AbstractInterceptor {
    6. private static final long serialVersionUID = 1L;
    7. public void destroy() {
    8. System.out.println("Destory");
    9. }
    10. public void init() {
    11. System.out.println("Init");
    12. }
    13. /**
    14. * @return result
    15. * */
    16. public String intercept(ActionInvocation invocation) throws Exception {
    17. System.out.println("action执行之前");
    18. String name = invocation.getInvocationContext().getName();
    19. System.out.println("请求方法:" + name);
    20. ActionContext ac = invocation.getInvocationContext();
    21. Map<String, Object> session = ac.getSession();
    22. boolean allow = name.equals("infolist") || name.equals("xwgg")
    23. || name.equals("pxdt") || name.equals("noticethrid")
    24. || name.equals("gqpx") || name.equals("gp")
    25. || name.equals("np") || name.equals("sp")
    26. || name.equals("wypx") || name.equals("zgks")
    27. || name.equals("shpx") || name.equals("fwxz")
    28. || name.equals("noticesec") || name.equals("filedown");
    29. if (name.equals("login") || allow) {
    30. // 如果用户想登陆,或者执行的是allow方法则不拦截,使之通过
    31. // invocation.invoke()继续运行拦截器后续的处理
    32. return invocation.invoke();
    33. } else {
    34. if (session.isEmpty() || session == null) {
    35. // 如果session为空,则让用户登陆
    36. return "login";
    37. } else {
    38. String userId = session.get("userId").toString();
    39. if (userId == null) {
    40. // session不为空,但是session中没有用户信息
    41. // 让用户登陆
    42. return "login";
    43. } else {
    44. // 用户已经登陆,登陆成功
    45. return invocation.invoke();
    46. }
    47. }
    48. }
    49. }
    50. }

    二、过滤不想被拦截的方法

    在默认的配置中,是拦截所有的方法,对于部分不需要拦截的方法,则需要进行特殊的处理。

    LoginInterceptor类中:

    1. String name = invocation.getInvocationContext().getName();

    这个name是获取请求的方法,由于,我们对部分方法可能不需要拦截,因此让其直接继续执行后续的处理操作。这种常见的情况是,我们前台首页的查询action,我们是不需要拦截的。我们可以将不需要拦截的方法定义在allow中,也可以定义在配置文件中。本文为了方便起见,定义了一个boolean的变量allow。

    1. if (name.equals("login") || allow) {
    2. return invocation.invoke();
    3. }

    invocation.invoke();是继续执行后续操作。

    三、修改Struts.xml配置文件,加入拦截器配置

    Struts.xml配置如下:

    1. <package name="author" namespace="/author" extends="struts-default">
    2. <interceptors>
    3. <interceptor name="login" class="com.xxx.util.LoginInterceptor"></interceptor>
    4. <interceptor-stack name="loginCheck">
    5. <interceptor-ref name="login"></interceptor-ref>
    6. <interceptor-ref name="defaultStack"></interceptor-ref>
    7. </interceptor-stack>
    8. </interceptors>
    9. <default-interceptor-ref name="loginCheck"></default-interceptor-ref>
    10. <global-results>
    11. <result name="login" type="redirect">/login.jsp</result>
    12. <result name="illegal" type="redirect">/illegal.jsp</result>
    13. </global-results>
    14. </package>

    这里需要说明一下的就是,对于这个拦截器的配置,可以加到需要拦截的package里面,也可以当度的放在一个package里面,然后其他的package继承我们的这个author package即可。

    1. <package name="User" namespace="/user" extends="struts-default,author">

    ps: 同样也可以在指定的action中进行配置

    1. <interceptor-ref name="loginCheck"></interceptor-ref>

    这个拦截器,但是这对每一个需要拦截的action都需要加入这个配置,对于大量的配置文件来说是比较繁琐的,因此我们只需定义一个package配置即可。

    另外,对于拦截器方法过滤也可以继承 MethodFilterInterceptor这个类来实现.


    转载自:http://blog.csdn.net/llhwin2010/article/details/8873034

    展开全文
  • 当用户主机A的浏览器中地址栏输入一个URL或网页点击一个超链接后,会发生一系列我们看不到操作,然后把网页内容呈现给用户。过程图如下: 图片参考...

    当用户在主机A的浏览器中地址栏输入一个URL或在网页中点击一个超链接后,会发生一系列我们看不到操作,然后把网页内容呈现给用户。过程图如下:

     

    图片参考https://blog.csdn.net/qq_24028753/article/details/75100484

    在这里,我把它分为如下四大步骤:

    第一步:DNS服务器首先对该链接进行域名解析,将域名转换为IP地址。

    域名解析过程用到的传输协议是UDP,查询方式分为递归查询和迭代查询。两种查询的访问顺序:本地域名服务器---根域名服务器---顶级域名服务器---权限域名服务器

    主机A向本地DNS的查询一般都采用递归查询。递归查询过程:如果主机A在本地域名服务器中查询不到IP地址,那么本地DNS就以DNS客户的身份代替主机A在根域名服务器中查询IP(本质上是DNS客户向根域名服务器发送查询请求,根域名服务器提供查询服务,返回查询结果。其中的根域名服务器是最高层次的域名服务器,所有的根域名服务器都知道所有的顶级域名服务器的域名和IP地址),如果查不到,根域名服务器再在顶级域名服务器中查询,就这样一层一层的向下查询,直到查询到域名对应的IP地址,再原路返回结果,否则就报错。这种传递性查询就称为递归查询。

    DNS服务器之间的交互查询一般都采用迭代查询。在迭代查询过程中,主机A向本地域名服务器进行递归查询,如果在本地域名服务器查询不到IP地址,本地域名采用迭代查询,再向根域名发送查询请求,根域名服务器不会替主机A去查询,而是告诉主机A的本地域名服务器顶级域名服务器的IP地址,然后主机A的本地域名服务器再访问顶级域名服务器,发送查询请求,反复查询,直到在某台服务器中查询对应的IP地址后,该服务器将结果返回给主机A的本地域名服务器,然后本地域名服务器再将结果返回给主机A。这种不断向主机A的本地域名服务器返回IP地址的查询称为迭代查询。

    经过上述查询之后,主机A将查到的目的IP地址封装到报文首部,数据传输任务就交给传输层。

    第二步:进行TCP三次握手,建立TCP连接。

    主机A的浏览器有了要访问的服务器的IP地址后,接着通过IP地址+端口号和服务器B进行TCP的三次握手,建立连接。

    首先A将TCP报文段首部的SYN置为1,选择一个初始序列号seq=x(TCP规定,SYN报文段不能携带数据,但要消耗掉一个序号),然后主机向服务器发出连接请求的报文段,进入SYN-SENT(同步已发送)状态。

    然后B收到请求报文段后,做出响应,将ACK置为1,确认号ack=x+1(大写表示状态,小写表示数值),选择自己的一个初始序列号seq=y,然后将该报文段发送给主机(该报文段也不带数据)。

    最后A收到B的确认后,需要向B也做出收到响应的确认,将ACK置为1,ack=y+1,seq=x+1。至此TCP连接已建立,A进入ESTABLISJED(已建立连接)状态,B收到确认后也进入ESTABLISJED状态,之后主机A和服务器B之间就可以进行数据传输了。

    第三步:进行数据传输。

    在传输过程中,主机A的浏览器首先将url地址通过http协议包装成请求报文发送给服务器B(http协议是面向事务的,本身是无连接的,虽然http使用了TCP连接,但通信双方在交换HTTP报文签不需要先建立HTTP连接),而此时,A只知道B的IP地址,可能还不知道B的mac地址,要想把数据传给B,就要用到地址解析协议(ARP,有些书将该协议划分到网络层,因为ARP要用到网络层的IP协议,有些书把它划分到数据链路层,因为它的用途是把IP地址解析成数据链路层的mac地址),ARP解析出mac地址的过程如下:

    如果A和B是第一次通信且在同一局域网,那么A就会在本局域网中广播一个ARP包,在ARP包中写入自己的IP地址和mac地址,并告诉局域网中的所有主机我要找XXX(B的IP地址)的mac地址。

    局域网中主机收到ARP包后,不是自己的IP地址则选择丢弃,B收到后,会将A的mac地址写入ARP高速缓存器中,并将自己的mac地址写入ARP包单播发送给A。

    A收到B发送的ARP包后也将B的mac地址写入自己的ARP高速缓存器中,之后A和B的通信就可以直接在ARP高速缓存器中找对方的mac地址了。

    如果A和B不在同一局域网,两个网络由R路由器相连,那么A在自己网络中广播ARP请求,会找到路由器R的mac地址,然后R在B所在的网络中广播ARP请求,找到B的mac地址,之后A和B就可以通过路由器R进行通信了。

    通过上述的ARP解析过程得到mac地址后,主机A将mac地址封装在帧首部,发送给B。

    服务器B将接收到请求报文通过http协议进行解析,然后将要发送的数据包装成响应报文发送给主机A,主机A收到数据后,浏览器继续进行HTML页面解析,遇到网页中的图片、cs、js、超链接等引用资源时,继续向服务器B发出请求,服务器B收到请求后做出响应(主要是找到链接中相应的资源)将数据分组打包返回给浏览器,如此反复进行,直至数据传输完成。

    第四步:四次挥手,关闭数据连接,浏览器将网页进行渲染呈现给用户。

    数据传输完成后需要进行四次挥手,断开连接,释放网络资源。

    首先主机A将FIN置为1,seq=u(u等于前面传输数据时A传送的最后一个报文段序号+1),向服务器B发送释放连接的报文段,并停止发送数据,A进入FIN-WAIT-1(终止等待1)状态。

    B收到释放连接的报文段后,将ACK置为1,ack=u+1,seq=v(v等于前面传输数据时B传送的最后一个报文段的序号+1),向A发送确认。这时B进入CLOSE-WAIT状态,TCP连接处于半关闭状态,也就是A已经没有数据要发给B了,但B还可以向A发送数据。A收到B的确认后进入FIN-WAIT-2状态,等待B发出释放连接的报文。

    若B也没有数据要传输A了,就使FIN=1,seq=w(在半关闭状态可能又向A发送了一些数据),ACK=1,ack=u+1(必须重复上次已发送过的确认号),向A发送释放连接的报文段。这时B进入LAST-ACK(最后确认)状态,等待A的确认。

    A收到B发送的释放连接报文段后,使ACK=1,ack=w+1,seq=u+1,向B发送确认,然后进入TIME-WAIT状态,此时TCP连接还没有释放掉,必须经过时间等待计时器设置的时间2MSL(Maximum Segment Lifetime 最长报文段寿命)后,A才进入CLOSED状态。

    注意:A进入TIME-WAIT状态后必须等待2MSL,是因为A向B发出确认后需要等待B接收,如果B在一个RTO(超时重传时间)内没收到A的确认,就会认为A没收到自己发送的释放连接的报文段,就会进行超时重传,A收到重传的报文段后就知道B没收到自己发送的确认,需要重新向B发送确认。

    小结:整个过程中主要用到的协议有:http,DNS(域名解析),UDP(域名解析时会用到),TCP,ARP(将IP地址转换为mac地址),IP协议,NAT(网络地址转换协议,如果是内网访问外网的话会用到)等。

     

    三次握手、四次挥手过程可参考https://blog.csdn.net/changyourmind/article/details/53127100

     

     

     

     

     

     

     

    展开全文
  • 1. 域名解析 2. 发起TCP的三次握手 3. 建立起TCP连接后发起http请求 4. 服务器响应http请求...5. 浏览器解析html代码,并请求html代码的资源(css JavaScript 图片) 6. 浏览器对页面进行渲染呈现 更多请参考。 ...
  • * 在浏览器地址栏输入地址后 敲回车 经历哪些过程 * https://news.163.com/index/html * 如果想访问一个服务器,咱们必须要知道的就是这个的服务器的IP地址 * DNS 域名系统 把访问的 域名对应的IP地址返回 ...
  • 在浏览器地址栏中,传数组参数

    千次阅读 2019-04-17 17:33:24
    spingboot项目在浏览器地址栏中,传数组参数,自己备注下
  • 1. 我们在浏览器中输入网址。 2. 浏览器查找域名对应的IP地址DNS查找过程为: 浏览器缓存->系统缓存->路由器缓存->ISP DNS缓存->递归搜索 递归搜索过程为:从根域名服务器到顶级域名服务器到你查询的域名服务器。 3...
  • web项目 启动tomcat后,浏览器地址栏输入中文访问不到,报404错误
  • 1.客户端浏览器获取用户在地址栏输入的域名。 2.客户端浏览器将域名发送给DNS域名系统,请求解析。 3.DNS解析域名得到相应的IP,返回给客户端浏览器。 4.客户端浏览器根据IP向服务器发起TCP三次握手,建立TCP连接。 ...
  • 在浏览器地址栏中查看cookie

    千次阅读 2012-04-16 18:25:23
    IE地址栏中输入javascript:alert(document.cookie) 或者地址栏直接打javascript:document.write(document.cookie); 转自:http://www.cnblogs.com/quanhai/archive/2010/03/20/1690350.html
  • 1、识别URL包括协议、域名、路径、端口,具体构成为:... 浏览器可以接受的字符编码集 Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型 Accept-Language 浏览器可接受的语言 Content-Length
  • 这是一道面试会经常问的问题...第二步:浏览器查找域名的IP地址 浏览器会把输入的域名解析成对应的IP,其过程如下: 1.查找浏览器缓存:因为浏览器一般会缓存DNS记录一段时间,不同浏览器的时间可能不一样,一般2-...
  • 浏览器地址栏输入url到显示页面步骤 查看缓存 无缓存,发起请求 有缓存,且可用(cache-control:max-age, expires过期时间),直接解析转码 有缓存,过期(Etag+If-None-Match, Last-Modified+If-Modified-since...
  • chrome浏览器地址栏输入过的记录该怎么删除? 1、电脑上找到chrome浏览器应用程序,并点击打开应用软件。 2、跳转的界面,输入网站的开头,会出现输入的记录。 3、按下电脑键盘上的方向键,将光标移动到需要...
  • 当我们在浏览器地址栏输入一个地址后,接下来到底会发生什么呢? 当你在浏览器中输入一个地址的时候,浏览器会从浏览历史记录,或者书签等地方模糊匹配出你想要的地址,提示补全url,对于Chrome来说,可以做到你...
  • chrome浏览器地址栏输入以下代码: data:text/html,<html contenteditable> 或者 浏览器开发者控制台console处输入 document.body.contentEditable = true css placeholder 文字颜色 ...
  • 在浏览器中输入www.baidu.com后执行的全部过程 从一道百度面试题到分析输入url到页面返回的过程(或者查询返回过程) 在浏览器中输入www.baidu.com后执行的全部过程 作为一个软件开发者,你一定会对网络应用...
  • 3. 浏览器根据IP地址与目标web服务器80端口上建立TCP连接4. 浏览器获取请求页面的html代码。5. 浏览器在显示窗口内渲染HTML。6. 窗口关闭时,浏览器终止与服务器的连接。 这其中最有趣的是第1步和第2步(域名...
  • 删除Chrome浏览器地址栏中某个网站的记录 如果Chrome地址栏访问过某网站,地址栏会记录这条网址,方便下次再次访问。登录次数越多,该条记录会越靠前。 但是,不想记录某些网址,如P站,A站,B站,C站,那么如何...
  • 当我们在浏览器网址中输入一个地址,点击回车后发生了以下事情。分为两种情况,http事务和https事务。先讲http事务:1、浏览器(客户端)进行地址解析。2、将解析出的域名进行dns解析。3、通过ip寻址和arp,找到目标...
  • 地址栏输入url, 要通过dns解析(浏览器是不能识别url地址的,需解析成ip地址), 返回相对应的IP地址, 建立tcp连接,(tcp三次握手) 发送Http请求, 服务器进行处理并返回Http报文, 浏览器渲染页面, ...
  • http://www.x.com/post.php为例 ...首先浏览器会判断URL的协议类型这里是HTTP协议(超文本传输协议)(查看更多协议)接下来通过域名查找IP1. 首先主机会检查本地host文件,判断是否相应域名的映射
  • 1、浏览器通过DNS域名解析到ip地址 2、浏览器通过TCP协议建立到服务器的TCP连接(TCP三次握手)  TCP三次握手:  1)客户端发送请求连接、请求报文  2)服务端接受连接后回复ACK报文,并为此次连接分配资源 ...
  • 当前端没有参数传递到...2 可以在浏览器地址栏添加对参数进行赋值,如下: http://localhost:8081/day17/findUserByServletServlet?currentPage=1&rows=1 3 其中currentPage及rows就是Servlet需要的参数 ...
  • 本文主要探究 在浏览器地址栏输入地址到页面渲染完成发生了什么 这个问题。通过对这个问题的探究,详细的梳理http、https、tcp及前端性能优化相关的问题。本文涉及到前端、后台、运维相关的工作,也会涉及到很多专有...
  • 本文转载自从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)与浏览器简单输入一个网址,解密其后发生的一切(http请求的详细过程),结合了笔者自己的一部分补充说明。 在浏览器地址栏输入URL,按下回车 ...
  • 1、在浏览器地址栏输入URL 2、浏览器查看缓存,如果请求资源缓存并且新鲜,跳转到转码步骤  ①如果资源未缓存,发起新请求  ②如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 173,671
精华内容 69,468
关键字:

在浏览器的地址栏中输入http