知识点:
l URL、URI
l HTTP基本思路
l DNS域名解析
l 协议栈和socket简介
1、 URL的结构
网址叫URL(Uniform Resource Locator,统一资源定位符)。
由“http:”、“ftp:”、“file:”、“mailto:”等开头,分别表示浏览器应当使用的访问方法。
访问 Web 服务器时用“http:”,而访问FTP(File Transfer Protocol,文件传送协议)服务器时用“ftp:”
![](https://i-blog.csdnimg.cn/blog_migrate/2b83503f3cc18a35628a161ee8878d84.png)
![](https://i-blog.csdnimg.cn/blog_migrate/741f95049ea1d274902fc59c4bea8c8a.png)
对于这种http://www.lab.glasscom.com/dir/没有指定文件名的URL来说,是一种缺省的表示方式,这个设置根据服务器不同而不同,大多数情况下是浏览器会默认访问名为index.html或者default.htm之类的文件。
对于这种http://www.lab.glasscom.com/whatisthis这种URL来说,如果服务器上存在名为whatisthis的文件,则将whatisthis作为文件名来处理;如果存在名为whatisthis的目录,则将whatisthis作为目录名来处理(服务器上是无法创建两个名字相同的文件和目录的)。
2、 HTTP的基本思路
HTTP(Hypertext Transfer Protocol,超文本传送协议)是浏览器用来访问Web服务器的一种协议。
![](https://i-blog.csdnimg.cn/blog_migrate/48fab3fd5d15e32f0e0c8ff991c7b1c1.png)
请求消息中包含的内容是“对什么(URI)”和“进行怎样的操作(方法)”两个部分。
URI(Uniform Resource Identifier,统一资源标识符)的内容是一个存放网页数据的文件名(例如“/dir1/file1.html”)或者是一个网页程序的文件名(“/dir1/program1.cgi”),URI也可以直接使用“http:”
开头的URL来作为URI。换句话说就是,这里可以写各种访问目标,而这些访问目标统称为URI。
方法表示需要让Web服务器完成怎样的工作,其中典型的例子包括读取URI表示的数据、将客户端输入的数据发送给URI表示的程序等。
![](https://i-blog.csdnimg.cn/blog_migrate/f955cd18e9c423f71ba0ee3c964e284e.png)
收到请求消息之后,Web服务器会对其中的内容进行解析,并根据这些要求来完成自己的工作,然后将结果存放在响应消息中。在响应消息的开头有一个状态码,它用来表示操作的执行结果是成功还是发生了错误(例如:遇到找不到的文件就会显示出404 Not Found的错误信息)。
![](https://i-blog.csdnimg.cn/blog_migrate/abc409405dadab0a471b5fef14aea72c.png)
由于每条请求消息中只能写1个URI,所以每次只能获取1个文件。如果需要获取多个文件,必须对每个文件单独发送1条请求。比如1个网页中包含3张图片,那么获取网页加上获取图片,一共需要向Web服务器发送4条请求。
请求消息和响应消息的格式如下图所示:
![](https://i-blog.csdnimg.cn/blog_migrate/e3d133248155a43f139c19cf350070bf.png)
3、 通过DNS服务器查询Web服务器IP地址
浏览器并不具备将HTTP请求消息发送到网络中的功能,需要委托操作系统来实现。在委托之前,需要查询网址中服务器名对应的IP地址。
实际的IP地址是一串32比特的数字,按照8比特(1字节)为一组分成4组,分别用十进制表示然后再用圆点隔开。通过子网掩码来区分IP地址的主机号和网络号两部分。
![](https://i-blog.csdnimg.cn/blog_migrate/3dee8a7a92f8e579033098f59f7e7db5.png)
DNS(Domain Name System,域名服务系统),将域名和其服务器的IP地址一一对应。
浏览器通过调用系统的Socket库中的DNS解析器,向DNS服务器发送查询消息,DNS服务器响应查询请求后向DNS解析器返回响应消息,DNS解析器提取出IP地址,写入浏览器指定的内存地址中。接下来,浏览器在向Web服务器发送消息时,只要从该内存地址取出IP地址,并将它与HTTP请求消息一起交给操作系统就可以了。
所谓的DNS解析器,实际上就是一段程序,包含在Socket库中。Socket库是用于调用网络功能的程序组件集合。其中的“gethostbyname()”函数实现对DNS解析器的调用。
![](https://i-blog.csdnimg.cn/blog_migrate/6d2709a64796bc38a084909ed10e6c15.png)
![](https://i-blog.csdnimg.cn/blog_migrate/bc7ce226bf73aef97eac5a98443d5c28.png)
向DNS服务器发送消息时,我们当然也需要知道DNS服务器的IP地址。只不过这个IP地址是作为TCP/IP的一个设置项目事先设置好的,不需要再去查询了。
来自DNS解析器的查询消息包含以下3种信息:
a) 域名:服务器、邮件服务器(邮件地址中@后面的部分)的名称;
b) Class:值是代表互联网的IN;
c) 记录类型:表示域名对应何种类型的记录。例如,当类型为A时,表示域名对应的是IP地址。
![](https://i-blog.csdnimg.cn/blog_migrate/1fe4ae372e27102b9a35a5eb8dd13296.png)
DNS服务器中的所有信息都是按照域名以分层次的结构来保存的。DNS中的域名都是用句点来分隔的,句点代表了不同层次之间的界限,越靠右的位置表示其层级越高。不同的DNS服务器中保存着不同层级的域。
![](https://i-blog.csdnimg.cn/blog_migrate/a3a13f37c4001118af64e5a20f95b4ff.png)
4、 委托协议栈发送消息
向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用Socket库中的程序组件。
![](https://i-blog.csdnimg.cn/blog_migrate/cd8e641266eae331460ee14a448f2600.png)
收发数据的操作分为若干个阶段,可以大致总结为以下4个:
1) 创建套接字(创建套接字阶段)
2) 与服务器端的套接字建立连接(连接阶段)
3) 收发数据(通信阶段)
4) 断开连接并删除套接字(断开阶段)
![](https://i-blog.csdnimg.cn/blog_migrate/e7ad847bba62f0f7586f4337fdfa8ded.png)
应用程序是通过“描述符”这一类似号码牌的东西来识别套接字的。
应用程序通过调用Socket库中的名为connect的程序组件来完成连接操作。connect函数需要传入三个参数:
1) 在创建套接字的时候由协议栈返回的描述符。协议栈根据这个描述符来判断到底使用哪一个套接字去和服务器端的套接字进行连接。
2) 通过DNS服务器查询得到的服务器的IP地址。
3) 端口号。端口号的规则是全球统一的,为了避免重复和冲突,端口号和IP地址一样都是由IANA(Internet Assigned Number Authority,互联网编号管理局)来统一管理的。当指定了IP地址和端口号时,就可以明确识别出某台具体的计算机上的某个具体的套接字。
描述符:应用程序用来识别本机套接字的机制。
IP 地址和端口号:客户端和服务器之间用来识别对方套接字的机制。