首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

浏览器是怎样向网卡发送数据的

每日前端夜话第352篇

作者:疯狂的技术宅

正文共:3400?字

预计阅读时间:10?分钟

从浏览器到浏览器内核

当我们在浏览器的地址栏中输入地址并回车后,浏览器可能会做一些预处理,比如 Chrome 会根据历史统计来预估所输入字符对应的网站,比如输入了“bai”,根据之前的历史发现会有很大的概率会访问 www.baidu.com ,因此就会在输入回车前就马上开始建立 TCP 链接甚至渲染了,这里面还有很多其它策略,感兴趣的同学推荐阅读 High Performance Networking in Chrome(http://aosabook.org/en/posa/high-performance-networking-in-chrome.html)。

接着是输入 URL 后的“回车”,这时浏览器会对 URL 进行检查,首先判断协议,如果是 http 就按照 Web 来处理,另外还会对这个 URL 进行安全检查,然后直接调用浏览器内核中的对应方法,比如 WebView 中的 loadUrl 方法。

在浏览器内核中首先会检查缓存,然后设置 UA 等 HTTP 信息,接着调用不同平台下的网络请求的方法。

浏览器和浏览器内核是两个不同的概念,浏览器指的是 Chrome、Firefox,而浏览器内核则是 Blink、WebKit、Gecko等,浏览器内核只负责渲染,GUI 及网络连接等跨平台工作则是由浏览器实现的

发送HTTP 请求

因为网络的底层实现与内核相关,所以在这里需要针对不同平台进行处理,从应用层角度来看主要是做两件事情:

通过 DNS 查询 IP

通过 Socket 发送数据

接下来就分别介绍这两方面的内容。

DNS 查询

DNS 查询其实是基于 UDP 来实现的,这里我们通过一个具体例子来了解它的查找过程,以下是使用dig fex.baidu.com +trace命令得到的结果:

1>?dig?fex.baidu.com?+trace

2

3;??DiG?9.11.4-P2-RedHat-9.11.4-16.P2.el7_8.6??fex.baidu.com?+trace

4;;?global?options:?+cmd

5.????????????11950???IN??NS??f.root-servers.net.

6.????????????11950???IN??NS??k.root-servers.net.

7.????????????11950???IN??NS??l.root-servers.net.

8.????????????11950???IN??NS??m.root-servers.net.

9.????????????11950???IN??NS??b.root-servers.net.

10.????????????11950???IN??NS??c.root-servers.net.

11.????????????11950???IN??NS??e.root-servers.net.

12.????????????11950???IN??NS??a.root-servers.net.

13.????????????11950???IN??NS??g.root-servers.net.

14.????????????11950???IN??NS??d.root-servers.net.

15.????????????11950???IN??NS??i.root-servers.net.

16.????????????11950???IN??NS??h.root-servers.net.

17.????????????11950???IN??NS??j.root-servers.net.

18;;?Received?251?bytes?from?192.168.0.1#53(192.168.0.1)?in?12?ms

19

20com.????????????172800??IN??NS??a.gtld-servers.net.

21com.????????????172800??IN??NS??b.gtld-servers.net.

22com.????????????172800??IN??NS??c.gtld-servers.net.

23com.????????????172800??IN??NS??d.gtld-servers.net.

24com.????????????172800??IN??NS??e.gtld-servers.net.

25com.????????????172800??IN??NS??f.gtld-servers.net.

26com.????????????172800??IN??NS??g.gtld-servers.net.

27com.????????????172800??IN??NS??h.gtld-servers.net.

28com.????????????172800??IN??NS??i.gtld-servers.net.

29com.????????????172800??IN??NS??j.gtld-servers.net.

30com.????????????172800??IN??NS??k.gtld-servers.net.

31com.????????????172800??IN??NS??l.gtld-servers.net.

32com.????????????172800??IN??NS??m.gtld-servers.net.

33com.????????????86400???IN??DS??30909?8?2?E2D3C916F6DEEAC73294E8268FB5885044A833FC5459588F4A9184CF?C41A5766

34com.????????????86400???IN??RRSIG???DS?8?1?86400?20200625050000?20200612040000?48903?.?OwfRn9tBOE2btL/z3HG5PQVyTXu2OUcZGLi9svkHFV0tomeI1p9bHhqr?GF/UDjf5a8VXNRoaSsSEQfgqwJT3UAOANK1vb3e+5jH2bV3Hg6/MAGG0?SuBfKv8Y1fjGgiLNC3NKmTWJ28WABHngymnGDpuqoC6xKmkVoD14ON7E?uHbBGxC0Uxt6D5R3WfbAAfbzZXzyPcD3WK1OpGaL6ASMB2xvdAZIkp/Z?l8QDmqZd86RX7haiVhxVG0mMrWxsN7XL2jVyRRFFl9UkApMk9/thPwNK?Rgkd4BPCvMPZTvsb+mPZA4InLxP6oPliZQm5sIWH8fEiyS+LgEReROzG?sqrpyw==

35;;?Received?1173?bytes?from?198.97.190.53#53(h.root-servers.net)?in?206?ms

36

37baidu.com.????????172800??IN??NS??ns2.baidu.com.

38baidu.com.????????172800??IN??NS??ns3.baidu.com.

39baidu.com.????????172800??IN??NS??ns4.baidu.com.

40baidu.com.????????172800??IN??NS??ns1.baidu.com.

41baidu.com.????????172800??IN??NS??ns7.baidu.com.

42CK0POJMG874LJREF7EFN8430QVIT8BSM.com.?86400?IN?NSEC3?1?1?0?-?CK0Q1GIN43N1ARRC9OSM6QPQR81H5M9A?NS?SOA?RRSIG?DNSKEY?NSEC3PARAM

43CK0POJMG874LJREF7EFN8430QVIT8BSM.com.?86400?IN?RRSIG?NSEC3?8?2?86400?20200618045106?20200611034106?39844?com.?nL7GSwad11x22Ff4/a3sjIA27DplTa0SZWNb9jnTs0+PYEehVKCT4a2g?TWgi5YHeqolDbwsK9oy7Hy1ZO3yhlhWUUAIyE5DE+iKuJCnD6fIvmXdq?lXsBBvUHK6wtHzIAPJ8PbCAl/PwSNjpZUZvv4YcEtLWU14yTsPPAM/wB?BxatwSt88sQrwYrLKqjnojEsmKVX1yi98pdT87BI/zKxzQ==

44HPVU6NQB275TGI2CDHPDMVDOJC9LNG86.com.?86400?IN?NSEC3?1?1?0?-?HPVVN3Q5E5GOQP2QFE2LEM4SVB9C0SJ6?NS?DS?RRSIG

45HPVU6NQB275TGI2CDHPDMVDOJC9LNG86.com.?86400?IN?RRSIG?NSEC3?8?2?86400?20200619061821?20200612050821?39844?com.?Iz4sOw47dg/aDbs/T9JSAXDiE88bqoj/kYbDQW5dO9NnQicyC5ZqEj0o?l1hxJHirVmJtCIXevkSy3eH1rrOH/Ni+oLlWZEBzQnucFK1C4WdBylF2?0OsgaG/AyHSD+9tWgMcQY+i28WBpxmxXvDLHY0oWb89UHMpcduqCh5+n?YXnbOHzjvaER/hX1ljveDo0z+HJIBtgY6/0NeFFY0ZWkcA==

46;;?Received?761?bytes?from?192.43.172.30#53(i.gtld-servers.net)?in?248?ms

47

48fex.baidu.com.????????600?IN??CNAME???sugar.n.shifen.com.

49n.shifen.com.????????86400???IN??NS??ns5.n.shifen.com.

50n.shifen.com.????????86400???IN??NS??ns2.n.shifen.com.

51n.shifen.com.????????86400???IN??NS??ns4.n.shifen.com.

52n.shifen.com.????????86400???IN??NS??ns3.n.shifen.com.

53n.shifen.com.????????86400???IN??NS??ns1.n.shifen.com.

54;;?Received?241?bytes?from?112.80.248.64#53(ns3.baidu.com)?in?32?ms

可以看到这是一个逐步缩小范围的查找过程,首先由本机所设置的 DNS 服务器( 192.168.0.1 )向 DNS 根节点查询负责 .com 区域的域务器,然后通过其中一个负责 .com 的服务器查询负责 baidu.com 的服务器,最后由其中一个 baidu.com 的域名服务器查询 www.baidu.com 域名的地址。

你在查询某些域名的时会可能会发现和上面不一样,最后将会看到有个奇怪的服务器抢先返回结果。。。

这里为了方便描述,忽略了很多不同的情况,比如 127.0.0.1 其实走的是 loopback,和网卡设备没关系;比如 Chrome 会在浏览器启动的时预先查询 10 个你有可能访问的域名;还有 Hosts 文件、缓存时间 TTL(Time to live)的影响等。

通过 Socket 发送数据

有了 IP 地址,就可以通过 Socket API 来发送数据了,这时可以选择 TCP 或 UDP 协议,具体使用方法这里就不介绍了,推荐阅读 Beej’s Guide to Network Programming(http://beej-zhcn.netdpi.net/)。

HTTP 常用的是 TCP 协议,由于涉及到 TCP 协议的具体细节的资料很容易就能找到,所以本文就不赘述了,只在这里谈一下 TCP 的队首阻塞问题:假设客户端发送了 3 个 TCP 片段(segments),编号分别是 1、2、3,如果编号为 1 的包传输时丢了,那么即便编号 2 和 3 已经到达也只能等待,因为 TCP 协议需要保证先后顺序,这个问题在 HTTP pipelining 下更严重,因为 HTTP pipelining 可以让多个 HTTP 请求通过一个 TCP 发送,比如发送两张图片,可能第二张图片的数据已经全收到了,但还得等第一张图片的数据传到。

为了解决 TCP 协议的性能问题,Chrome 团队提出了 QUIC 协议,它是基于 UDP 实现的可靠传输,比起 TCP,它能减少很多往返(round trip)时间,还有前向纠错码等功能。目前 Gmail、Google Search、blogspot、Youtube 等几乎大部分 Google 产品都在使用 QUIC,你可以在 Chrome 中的chrome://flags/#enable-quic页面找到它的配置。

虽然国内很多大厂也在研究 QUIC 的应用,但离大范围普及还有较长的一段距离,因为如果针对 TCP 进行优化,需要升级系统内核。

浏览器对同一个域名有连接数是有限制得,[一般是 6 个(http://www.browserscope.org/?category=network&v=top),Chrome 团队曾做过实验,发现从 6 改成 10 后性能反而下降了,造成这个现象的因素有很多,如建立连接的开销、拥塞控制等问题,而像 SPDY、HTTP 2.0 协议尽管只使用一个 TCP 连接来传输数据,但性能反而更好,而且还能实现请求优先级。

另外,因为 HTTP 请求是纯文本格式的,所以在 TCP 的数据段中可以直接分析 HTTP 的文本。

Socket 在内核中的实现

前面说到浏览器的跨平台库通过调用 Socket API 来发送数据,那么 Socket API 是如何实现的呢?

以 Linux 为例,它实现在 socket.c(http://lxr.linux.no/linux+v3.14.4/net/socket.c)?中,如果你想深入研究一下,推荐看 Linux kernel map(http://www.makelinux.net/kernel_map/),它标注出了关键路径的函数,方便学习从协议栈到网卡驱动的实现。

底层网络协议的具体例子

接下来如果继续介绍 IP 协议和 MAC 协议可能会把大家搞晕,所以下面用 tcpdump 来通过具体例子讲解,以下是在请求百度首页时抓取到的网络数据:

可以看到最前面的三次通信是 TCP 协议的三次握手过程,在第四次通信中被选中的部分为 HTTP 协议(Hypertext Transfer Protocol),在 HTTP 之前有 54 字节(0x36),这就是底层网络协议所带来的开销,我们接下来对这些协议进行分析。

在 HTTP 之上是 TCP 协议(Transmission Control Protocol),它的具体内容如下图所示:

通过底部的二进制数据,可以看到 TCP 协议是加在 HTTP 文本前面的,它有 20 个字节,其中定义了本地端口(Source port)和目标端口(Destination port)、顺序序号(Sequence Number)、窗口长度等信息,以下是 TCP 协议各个部分数据的完整介绍:

1?0???????????????????1???????????????????2???????????????????3

2?0?1?2?3?4?5?6?7?8?9?0?1?2?3?4?5?6?7?8?9?0?1?2?3?4?5?6?7?8?9?0?1

3+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

4|??????????Source?Port??????????|???????Destination?Port????????|

5+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

6|????????????????????????Sequence?Number????????????????????????|

7+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

8|????????????????????Acknowledgment?Number??????????????????????|

9+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

10|??Data?|???????????|U|A|E|R|S|F|???????????????????????????????|

11|?Offset|?Reserved??|R|C|O|S|Y|I|????????????Window?????????????|

12|???????|???????????|G|K|L|T|N|N|???????????????????????????????|

13+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

14|???????????Checksum????????????|?????????Urgent?Pointer????????|

15+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

16|????????????????????Options????????????????????|????Padding????|

17+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

18|?????????????????????????????data??????????????????????????????|

19+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

20

具体每个字段的作用这里就不介绍了,感兴趣的同学可以通过阅读 RFC 793(http://tools.ietf.org/html/rfc793),并结合抓包分析来理解。

需要注意的是,在 TCP 协议中并没有 IP 地址信息,因为这是在上一层的 IP 协议中定义的,如下图所示:

IP 协议同样是在 TCP 前面的,它也有 20 字节,在这里指明了版本号(Version)为 4,源(Source) IP 为192.168.1.106,目标(Destination) IP 为119.75.217.56,因此 IP 协议最重要的作用就是确定 IP 地址。

因为 IP 协议中可以查看到目标 IP 地址,所以如果发现某些特定的 IP 地址,某些路由器就会。。。

但是,光靠 IP 地址是无法进行通信的,因为 IP 地址并不和某台设备绑定,比如你的笔记本的 IP 在家中是192.168.0.11,但到公司就变成10.0.11.11了,所以在底层通信时需要使用一个固定的地址,这就是 MAC(media access control) 地址,每个网卡出厂时的 MAC 地址都是固定且唯一的。

因此再往上就是 MAC 协议,它有 14 字节,如下所示:

当一台电脑加入网络时,需要通过 ARP 协议告诉其它网络设备它的 IP 及对应的 MAC 地址是什么,这样其它设备就能通过 IP 地址来查找对应的设备了。

现在我们搞清了标题中的问题,不过这里面还有大量的细节没介绍,建议大家通过下面的书籍进一步学习。

扩展学习

往期精彩回顾

怎样为你的 Vue.js 单页应用提速

10 个实用的 JavaScript 小技巧

它改变了 JavaScript 的体系结构——Webpack 5 Module Federation

与 JavaScript 模块相关的所有知识点

我们是怎样优化 V8 中的指针压缩的

当一个模块被导入两次时,会发生什么?

ReactJS 与 VueJS:两种流行前端 JS 框架之战

十分钟搞定 TypeScript + webpack 配置

18 个漂亮的 Bootstrap 模板

前端程序员要懂的 UI 设计知识

如果觉得有帮助,请点击“在看”让更多小伙伴知道

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200612A0PFS300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com