代码改变世界

输入URL之后都发生了什么

2015-06-12 15:02  轩脉刃  阅读(4148)  评论(5编辑  收藏

输入URL之后都发生了什么

这个标题印象中已经有很多讨论了。也来说说这个话题。

从头开始,当你的电脑使用网线连接到网络的时候,我们都知道,这个时候你的电脑会获取一个IP,这个IP就是你的唯一标识了。好了继续,你在浏览器中敲入了http://www.sina.com,开始你的网络之旅。那么这个时候问题来了,我们都知道你这个数据是从哪里的机器来的呢?比如sina的提供这个服务的机器也有个IP,那么你敲入的www.sina.com怎么会定位到sina提供机器的IP呢?这里就是DNS概念了。

DNS

好了,这里其实最需要的就是域名与IP的对应关系,由于世界上的服务太多了,每个服务都有需要有一个域名和ip的映射,这个量太大了。所以我们将域名按照小数点进行划分。sina.com,最后一个小数点后面的叫做顶级域名,顺次叫做二级域名,三级域名。域名服务商也不是一家,有很多家,大致也是树形结构,其中管理顶级域名的公司全世界只有13家,其中唯一的一台主服务器在美国,其他的从域名服务器分别在美国,瑞典,荷兰和日本。

.com:表示商业机构
.net:表示网络服务机构
.org:表示非营利性组织
.gov:表示政府机构
.edu:表示教育机构

我们可以使用dig +trace命令来获取每次域名请求的情况

[yejianfeng@iZ23u681ae1Z ~]$ dig www.126.com +trace

; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.23.rc1.el6_5.1 <<>> www.126.com +trace
;; global options: +cmd
.           255442  IN  NS  g.root-servers.net.
.           255442  IN  NS  f.root-servers.net.
.           255442  IN  NS  i.root-servers.net.
.           255442  IN  NS  e.root-servers.net.
.           255442  IN  NS  d.root-servers.net.
.           255442  IN  NS  m.root-servers.net.
.           255442  IN  NS  j.root-servers.net.
.           255442  IN  NS  a.root-servers.net.
.           255442  IN  NS  k.root-servers.net.
.           255442  IN  NS  l.root-servers.net.
.           255442  IN  NS  c.root-servers.net.
.           255442  IN  NS  b.root-servers.net.
.           255442  IN  NS  h.root-servers.net.
;; Received 496 bytes from 10.202.72.116#53(10.202.72.116) in 2 ms

com.            172800  IN  NS  k.gtld-servers.net.
com.            172800  IN  NS  b.gtld-servers.net.
com.            172800  IN  NS  h.gtld-servers.net.
com.            172800  IN  NS  f.gtld-servers.net.
com.            172800  IN  NS  d.gtld-servers.net.
com.            172800  IN  NS  g.gtld-servers.net.
com.            172800  IN  NS  c.gtld-servers.net.
com.            172800  IN  NS  m.gtld-servers.net.
com.            172800  IN  NS  j.gtld-servers.net.
com.            172800  IN  NS  a.gtld-servers.net.
com.            172800  IN  NS  i.gtld-servers.net.
com.            172800  IN  NS  e.gtld-servers.net.
com.            172800  IN  NS  l.gtld-servers.net.
;; Received 501 bytes from 192.5.5.241#53(192.5.5.241) in 33 ms

126.com.        172800  IN  NS  ns2.nease.net.
126.com.        172800  IN  NS  ns3.nease.net.
126.com.        172800  IN  NS  ns4.nease.net.
126.com.        172800  IN  NS  ns5.nease.net.
126.com.        172800  IN  NS  ns6.nease.net.
126.com.        172800  IN  NS  ns7.nease.net.
126.com.        172800  IN  NS  ns1.nease.net.
126.com.        172800  IN  NS  ns8.nease.net.
;; Received 342 bytes from 192.41.162.30#53(192.41.162.30) in 275 ms

www.126.com.        18000   IN  CNAME   mcache.mail.163.com.
mcache.mail.163.com.    18000   IN  CNAME   email.163.com.lxdns.com.
;; Received 93 bytes from 61.135.255.140#53(61.135.255.140) in 29 ms

上面就是说我们请求了5次才寻找出准确的提供服务的机器。

那么问题来了,这13台根域名服务器如果挂了,怎么办?比如2014年1月21日出现过顶级域名服务出错的情况,导致了域名服务器错误的情况。那么这种情况,只能说是世界崩溃了。你百度不了,google不了,网络就请求不了了。一出这种问题,很多流传的方法都是直接绑定DNS服务器到8.8.8.8,这个是google的服务器。

再说一个DNS的案例,13个顶级的域名服务商在解析了顶级域名之后,会把其他对应的域名解析防盗

好了,这里有个优化的点了,我一般浏览网站的时候都是连续请求一个网站的几个页面,每次都去域名服务商那边查询这个域名的服务IP,这本身就是脑残的事情。对于这种脑残的事情,程序员肯定是不会做的,所以在本机和浏览器保存域名和IP的查询。好了,现在所有浏览器一起讨论的方法就是请求先去浏览器DNS缓存中查找,比如chrome中可以使用

chrome://net-internals/#dns

进行缓存查询。

然后是本机的DNS缓存,本地的DNS缓存在windows可以通过ipconfig /displaydns进行查找。本地还有一个可以让人工干预DNS解析的地方,就是hosts文件,有个很好用的工具SwitchHosts可以来进行hosts文件设置。

路由

好了,知道了对方提供服务的机器地址了,但是不幸的事情发生了,它是在上海的,我是在北京的,我们两个之间并没有直接的电线进行连接。那么怎么办呢?程序员也想到了一个办法,驿站。在互联网中间建立很多站点,这些站点提供的一种服务叫转接服务。比如我想要连接到www.126.com所在的服务器怎么办呢?我可能要中间跳转10-20次才能到达它的服务器。第一次调转到北京燕郊,第二次跳转到河北,...使用traceroute就可以查看你到达一个ip中间跳转了几次。

那么是谁那么好心建立这些驿站呢?就是运营商。中国现在有6大运营商:中国移动,中国联通,中国电信,中国网通,中国铁通和中国卫通。然后长城宽带据说厚劲勃发,要做第七大运营商。当然这个网络肯定不是让大家免费用的,这里大家就知道了,我们平时交的网费是花在哪里了。

好了,运营商的厉害之处就知道了吧,如果有运营商使坏,你本来从北京传递消息“我爱你”给上海的一台机器,但是运营商路由传递的过程中把这个信息改成了“分手吧”。好了,这下你哭都没法子了。这个就叫做运营商劫持。现在有的运营商劫持不会很暴露,但是加个广告,加个js还是很有可能的。

TCP握手

好了,我们现在找到了提供服务的机器了,我们想要从这个机器上获得一个页面。机器的行为和人的行为很像。对于人来说,A要和B握手,A先伸出手,B也伸出手回应,你好,我是B,然后A再回应,你好,我是A。这样一个握手认识的环节就完成了。

在互联网中,也是这样的一个三次握手的顺序。A要和B服务进行交互,要经过三次握手的环节。A发送一个请求给B,B回应了一个请求,然后A再发送一个确认请求给B。这样两个人的信任关系就搭建完成了。

好了,这里插入说一种攻击方式。如果我现在有很多小弟,然后我让这些小弟都轮番和你进行第一次握手,就是那次伸手环节。但是等你伸手之后,我不对你进行回应,你就会傻傻在那边等待我的回应。这种攻击就叫做SYN FLOOD攻击。

搭建完成之后两边就进行了数据交互。这里数据交互的部分我们等会再说。数据交互完之后,这里就有一个结束交互的环节了。

再想想恋人是如何如何分手呢?两个恋人决定要分开了,A和B说,我已经不爱你了,B和A说,好,我也已经不爱你了。然后由于A和B都已经确定我们互相不爱了,B就干脆的说,我们分手吧,A也非常干脆地说,分手吧。然后两人就分手了。

这个过程术语叫做四次挥手环节。A和B是双工的,双工的意思就是A和B都有接收信道和发送信道。A发送结束信号给B,并且把自己的发送信道设置为待关闭状态,B收到A的结束信号之后,先发送一个信号给A,我也可以结束了,并且自己关闭了发送信道。然后再发送一个信号给A,告诉A我最后接收到你的确认之后就把接收信道关闭了。A收到这个确认信号之后,最后发送了一个信号,关闭吧,然后把自己的接收信号给关闭了,也把自己的发送信号给彻底关闭了。B收到这个信号之后,就最后把自己的发送和接收信道就关闭了。

交互消息内容

好了,现在回到双方交互的时候,进行数据传递。首先,A要的其实不是数据,而是一个有图片,有字体的页面,B能给的是一个数据。这里就有一个问题了,如何使用数据来描述一个页面呢?这里就需要有一个描述页面的语言。就叫做HTML。

如果给你一个页面,让你描述它。你一定会这么描述,整个页面分为上下两个部分,上面部分10厘米,下面部分100厘米,上面的部分底色为蓝色,又分为几个标题。我要说,你真聪明。实际上我们的页面切图也就是这么切图的。不过我们的语言不是这样平白的语言,而是用HTML语言。

<div style="heigh:10px" >
    <div style="width:10px;float:left" ></div>
    <div style="width:10px;float:left" ></div>
    <div style="width:10px;float:left" ></div>
</div>
<div style="heigh:100px"></div>

这HTML语言是1982年之后就创建的。在逐步发展演变过程中成为了国际的标准,现在所有的浏览器都支持这个语言。HTML现在由一个国际组织万维网联盟(W3C)来进行维护。

HTML现在的发展历程已经到了HTML5。HTML1.0, HTML2.0, HTML3.0,HTML4.0,也都是有的,现在最新的是HTML5,2014年10月完成标准制定。在这个之前,HTML5的草案其实已经发布很久了,但是各个浏览器对于它的支持也都不一致,等到5.0正式发布之后,现在浏览器对于HTML5的支持已经很强大了。

好了,一般来说,客户端获取到了HTML,这个过程就完成了。但是现在角度换到服务端。如果像新闻一样,所有人看到的东西都一样,那么就很简单了,我把一个HTML文件放在服务器端,你过来拿就行了。但是偏偏现在同样一个新闻,不同的人看到的东西是不同的。这两种情况就叫做“静态页面”和“动态页面”。动态页面需要完成一定的业务逻辑才能返回一个HTML页面。那么这个时候服务端就需要写一些逻辑,于是就有了写这些逻辑的语言了。现在我们大多数使用的语言有PHP,JAVA,PYTHON等。各种语言有各种语言的优势,但是总的目的就是为了生成动态页面。

AJAX

好了,我们换回浏览器角度,我们获取到HTML之后,然后根据HTML的语意,进行渲染,描绘出我们需要的页面样式。

但是,这种页面是“死”的。意思是什么。这种页面我想要在文本中输入一个字,然后文本提示我,还可以输入几个字。这个功能就需要页面有一个功能“如果用户输入了一个字,计算距离20个字还有多少字,修改提示文本”。这个逻辑就需要脚本语言来做,这个就是JavaScript。最早javascript是由一家国外公司netscape进行设计的,后来逐步成为了一种国际标准。现在所有的浏览器都支持javascript语言了。

实际使用中,我们常常会碰到一种需求,我们希望我点击一个按钮,这个按钮不要跳转到另外一个页面,而是直接在这个页面内和服务端做操作,做完操作之后,修改当前页面的一个元素或者内容。这样我们的执行效率就会提高了。这种逻辑,我们专门给它一个名词“AJAX”,由javascript对服务器端发起一个网络请求,比如请求修改用户名称,然后服务器返回说修改成功了,然后客户端就进行页面元素的修改。