浏览器是一个具备多种客户端功能的综合性客户端软件,因此它需要 一些东西来判断应该使用其中哪种功能来访问相应的数据,而各种不同的 URL 就是用来干这个的,比如访问 Web 服务器时用“http:”,而下载上传文件访问 FTP 服务器时用“ftp:”。读取客户端计算机本地文件时,用file://;发送邮件用mailto:; (试了一下在浏览器里面真的可以看本地文件好神奇)
尽管 URL 有各种不同的写法,但它们有一个共同点,那就是 URL 开 头的文字,即“http:”“ftp:”“file:”“mailto:”这部分文字都表示浏览器应当使用的访问方法。比如当访问 Web 服务器时应该使用 HTTP 协议,而 访问 FTP 服务器时则应该使用 FTP 协议。因此,我们可以把这部分理解为 访问时使用的协议类型
-
www.lab.glasscom.com/dir1/file1.… 为例
www.lab.glasscom.com 是web服务器名称
文件的路径名是 /dir1/file1.html -
有时候我们也会见一些不太一样的 URL,例如下面这个 URL 是以“/”来结尾的,比如 www.lab.glasscom.com/dir/ 以“/”结尾代表 /dir/ 后面本来应该有的文件名被省略了。根据 URL 的规则,文件名可以像前面这样省略。其实,我们会在服务器上事先设置好文件名省略时要访问的默认文件名。这个设置根据服务器不同而不同,大多数情况下是 index.html 或者 default.htm 之类的文件名。因此,像前面这样省略文件名时,服务器就会访问 /dir/index.html 或者 /dir/default.htm
-
www.lab.glasscom.com 这次连结尾的“/”都省略了。像这样连目录名都省略时,真不知道到底在请求哪个文件了,实在有些过分。不过,这种写法也是允许的。当没有路径名时,就代表访问根目录下事先设置的默认文件,也就是 /index. html 或者 /default.htm 这些文件,这样就不会发生混乱了
-
www.lab.glasscom.com/whatisthis 一般来说,这种情况会按照下面的惯例进行处理:如果 Web 服务器上存在名为 whatisthis 的文件,则将 whatisthis 作为文件名来处 理;如果存在名为 whatisthis 的目录,则将 whatisthis 作为目录名来处理
使用POST方法时,URI会指向web服务器中运行的一个应用程序的文件名,典型的例子包括“index.cgi","index.php"
尽管浏览器能够解析网址并生成 HTTP 消息,但它本身并不具备将消息发送到网络中的功能,因此这一功能需要委托操作系统来实现,因为发送消息的功能对于所有的应用程序来说都是通用的,因此让操作系统来实现这一功能,其他应用程序委托操作系统来进行操作,这是一个比较合理的做法。在委托操作系统发送消息时,必须要提供的不是通信对象的域名,而是它的IP地址。因此,在生成 HTTP 消息之后,下 一个步骤就是根据域名查询 IP 地址。
实际的 IP 地址是一串 32比特的数字,按照 8 比特(1 字节)为一组分成 4 组,分别用十进制表示 然后再用圆点隔开。在 IP 地址的规则 中,网络号和主机号连起来总共是 32 比特,但这两部分的具体结构是不固定的。在组建网络时,用户可以自行决定它们之间的分配关系。因此,我 们还需要另外的附加信息来表示 IP 地址的内部结构。这一附加信息称为子网掩码,子网掩码的格式是一串与IP地址长度相同的32比特数字,其左边一半都是1,右边一半都是0。其中,子网掩码为1的部分表示网络号,子网掩码为0的部分表示主机号
为什么不直接用路由名称来确定通信对象,反而还要根据名称去找IP地址呢
IP 地址的长度为32比特,也就是4字节,相对地,域名最短也要几十个字节,最长甚至可以达到255 字节。换句话说,使用IP地址只需要处理4字节的数字,而域名则需要处理几十个到255个字节的字符,这增加了路由器的负担,传送数据也会花费更长的时间;域名并不仅是长,而且其长度是不固定的。处理长度不固定的数据比处理长度固定的数据要复杂,这也是造成效率低下的重要原因之一
因此我们让人使用名称,让路由器使用IP地址,这样中间就需要有一个机制通过名称得到IP地址或者通过IP地址查询名称,这个机制就是DNS
向 DNS 服务器发出查询,也就是向 DNS 服务器发送查询消息,并接收服务器返回的响应消息。换句话说,对于 DNS 服务器,我们的计算机上 一定有相应的 DNS 客户端,而相当于 DNS 客户端的部分称为 DNS 解析器,或者简称解析器。通过 DNS 查询 IP 地址的操作称为域名解析,因此 负责执行解析(resolution)这一操作的就叫解析器(resolver)了,解析器实际上是一段程序,它包含在操作系统的 Socket 库中。首先,库就是一堆通用程序组件的集合,其他的应用程序都需要使用其中的组件,Socket 库也是一种库,其中包含的程序组件,可以让其他的应用程序调用操作系统的网络功能,而解析器就是这个库中的其中一种程序组件。
具体来说,在编写浏览器等应用程序的时候,只要像图中这样写上解析器的程序名称“gethostbyname”以及 Web 服务器 的域名“www.lab.glasscom.com” 就可以了,这样就完成了对解析器的调用
调用解析器后,解析器会向 DNS 服务器发送查询消息,然后 DNS 服务器会返回响应消息。响应消息中包含查询到的 IP 地址,解析器会取出 IP 地址,并将其写入浏览器指定的内存地址中。接下来,浏览器在向 Web 服务器发送消息时,只要从该内存地址取出 IP 地址,并将它与 HTTP 请求消息一起交给操作系统就可以了
DNS是怎么找到IP的
应用程序(浏览器)委托收发数据,首先是套接字创建阶段。客户端创建套接字的操作非常简单,只要调 用 Socket 库中的 socket 程序组件,套接字创建完成后,协议栈会返回一个描述符,应用程序会将收到的描述符存放在内存中。描述符是用来识别不同的套接字的,打开两个浏览器窗口,同 时访问两台 Web 服务器。这时,有两个数据收发操作在同时进行,也就需要创建两个不同的套接字。当创建套接字后,我们就可以使用这个套接字来执行收发数据的操作了。这时,只要我们出示描述符, 协议栈就能够判断出我们希望用哪一个套接字来连接或者收发数据了(应用程序是通过“描述符”这一类似号码牌的东西来识别套接字的)
接下来,我们需要委托协议栈将客户端创建的套接字与服务器那边的 套接字连接起来。应用程序通过调用 Socket 库中的名为 connect 的程序组 件来完成这一操作,当调用 connect 时,需要指定描述符、 服务器 IP 地址和端口号这 3 个参数,第 1 个参数,即描述符,就是在创建套接字的时候由协议栈返回的那个描述符。connect 会将应用程序指定的描述符告知协议栈,然后协议栈根据这个描述符来判断到底使用哪一个套接字去和服务器端的套接字进行连接,并执行连接的操作;第 2 个参数,即服务器 IP 地址,就是通过 DNS 服务器查询得到的我 们要访问的服务器的 IP 地址。在 DNS 服务器的部分已经讲过,在进行数 据收发操作时,双方必须知道对方的 IP 地址并告知协议栈。这个参数就是 那个 IP 地址了;第 3 个参数,即端口号,只要知道了IP地址,我们就可以识别出网络上的某台计算机。但是,连接操作的对象是某个具体的套接字,因此必须要识别到具体的套接字才行(当同时指定 IP 地址和端口号时,就可以明确识别出某台具体的 计算机上的某个具体的套接字),服务器上所使用的端口号是根据应用的种类事先规定好的。比如 Web 是 80 号端口,电子邮件是 25 号端口,只要指定了事先规定好的端口号,就可以连接到相应的服务器程序的套接字,那可能会问既然确定连接对象的套接字需要使用端口号,那么服务器也得知道客户端的套接字号码才行吧,这个问题是怎么解决的 呢?事情是这样的,首先,客户端在创建套接字时,协议栈会为这个套接字随便分配一个端口号。接下来,当协议栈执行连接操作时,会将这个随便分配的端口号通知给服务器