Java网络编程之应用层

本篇介绍计算机网络中的应用层,内容皆总结摘抄自《计算机网络:自顶向下方法》,仅作笔记。

应用层协议原理

我们大多数It工作者都是在研发网络应用程序,网络应用程序的核心是写出能够运行在不同端系统和通过网络彼此通信的程序。在开发前,应该对应用程序有一个宽泛的体系结构计划。

网络应用程序体系结构

网络应用程序的体系结构与网络的体系结构有明显的不同。从应用程序研发者的角度看,网络体系结构是固定的,并且为应用程序提供了特定的服务集合。应用程序体系结构由应用程序研发者设计,规定了如何在各种端系统上组织该应用的程序。现代网络应用程序中所使用的有两种主流体系结构:客户-服务器体系结构和对等(P2P)体系结构。

在客户-服务器体系结构(client-server architecture)中,有一个总是打开的主机称为服务器,它服务于来自许多其它成为客户的主机的请求。作为一个Java工程师,我们大多数人开发的Web程序都属于这种体系结构。在这种体系结构中,Web服务器服务于来自浏览器(运行在客户主机上)的请求,当Web服务器接收来自某客户对某对象的请求时,它向该客户发送所请求的对象作为响应。客户-服务器体系结构中的服务器具有固定的、周知的地址(IP地址),并且总是打开的,因此客户总是能够向该服务器的IP地址发送分组来与其联系。

在一个客户-服务器应用中,可能会出现一台单独的服务器主机跟不上它所有客户请求的情况。例如淘宝、百度等等网站如果只有一台服务器来处理所有请求,很明显不能支撑这么多的访问量。为此,这些网站都配置了大量主机的数据中心来创建强大的虚拟服务器。

一个P2P体系结构(P2P architecture)相比客户-服务器体系结构,对位于数据中心的专用服务器有最小的依赖,甚至没有依赖。应用程序在间断连接的主机之间使用直接通信,这些主机对被称为对等方。这些对等方不为服务提供商所有,且对等方直接的通信不通过专门的服务器,该体系结构因此被称为对等方到对等方的。P2P体系结构常见的应用包括文件共享、对等方协助下载加速器(例如迅雷)、因特网电话和视频会议等。

有些应用具有混合的体系结构,结合了客户-服务器和P2P的元素。例如,对许多即时讯息应用来说,服务器用于跟踪用户的IP地址,但用于到用户的报文在用户主机之间直接发送,而无须通过中间服务器。

进程通信

多个端系统上的程序是通过进程来通信的,一个进程可以被认为是运行在端系统中的一个程序。在两个不同端系统上的进程,通过跨越计算机网络交换报文而相互通信。发送进程生成并向网络中发送报文;接收进程接收这些报文并可能通过回送报文进行响应。

网络应用程序由成对的进程组成,这些进程通过网络相互发送报文。在一对进程之间的通信会话场景中,发起通信(即在该会话开始时发起与其他进程的联系)的进程被标识为客户,在会话开始时等待联系的进程是服务器。例如,在Web中,一个浏览器进程首先向一台Web服务器进程发起联系,因此该浏览器进程是客户,该Web服务器进程时服务器。在P2P文件共享中类似,当对等方A请求对等方B发送文件时,此时对等方A是客户,对等方B是服务器。

进程必须且只能通过套接字(socket)的软件接口向网络发送报文和从网络接收报文。套接字是同一台主机内应用层与运输层之间的接口,由于套接字是建立网络应用程序的可编程接口,因此套接字也称为应用程序和网络之间的应用程序编程接口(Application Programming Interface,API)。应用程序开发者可以控制套接字在应用层端的一切,但对该套接字的运输层端几乎没有控制权。

一台主机上运行的进程为了向另一台主机上运行的进程发送分组,接收进程必须要有一个地址。为了标识该接收进程,接收地址需要定义两种信息:

  1. 目的主机的IP地址;
  2. 目的主机中接收进程的标识符。

IP地址是一个32比特的量,并且能够唯一地标识某台主机。由于一台主机上可以运行多个网络应用,因此只有主机的IP地址是不够的,找到了目的主机,还需要找到目的主机上的目标进程。端口号(port number)可以帮助我们找到接收进程。通过IP地址+端口号可以唯一确定目的主机上的目的进程。

可供应用程序使用的运输服务

套接字是应用程序进程和运输层协议之间的接口。在发送端的应用程序将报文推进该套接字,运输层协议从接收进程的套接字得到该报文。而因特网提供了不止一种运输层协议,不同的运输层协议为应用程序提供不同的服务。从以下四个方面可以对应用程序服务的要求进行分类以帮助我们更好的挑选运输层协议:可靠的数据传输、吞吐量、定时和安全性。

  • 可靠的数据传输

这篇文章中提到过,分组在传输过程中可能会因为各种原因丢失。对于某些应用来说,数据丢失可能会造成灾难性的后果,例如一些金融应用等等。为了支持这些应用,一些运输层协议就提供了可靠数据传输(reliable data transfer),即发送进程只要将数据传递进套接字,就可以保证该数据能完好的到达接收进程。

  • 吞吐量

在沿着一条网络路径上的两个进程之间的通信会话场景中,可用吞吐量指的是发送进程能够像接受进程交付比特的速率。对与一些特殊的应用,它们可能需要以某种特定的速率来确保吞吐量,例如某个应用程序要求r比特/秒的确保吞吐量,运输层协议可以确保吞吐量总是最少为r比特/秒。具有吞吐量要求的应用程序被称为带宽敏感的应用,许多多媒体应用都是带宽敏感的。根据当时可用的带宽或多或少地利用可供使用的吞吐量的应用称为弹性应用,电子邮件、文件传输等都属于弹性应用。

  • 定时

类似吞吐量保证,运输层协议也能提供定时保证。例如,保证发送方注入进套接字的每个比特到达接收方的套接字不迟于100ms。

  • 安全性

运输层协议能够为应用程序提供一种或多种安全性服务。例如,在发送主机中,运输层协议能够加密由发送进程传输的所有数据,在接收主机中,运输层协议能够在将数据交付给接受进程之前解密这些数据。这种服务将在发送和接收进程之间提供机密性,以防该数据以某种方式在两个进程间被观察到。

因特网提供的运输服务

因特网为应用程序提供了两个运输层协议,即TCP和UDP。

  • TCP服务

TCP服务模型包括面向连接服务和可靠数据传输服务。当应用程序采用TCP作为其运输层协议时,该应用程序就能获得来自TCP的这两种服务。

面向连接的服务指的是在应用层数据报文开始流动之前,TCP就让客户和服务器互相交换运输层控制信息。经过一个握手过程,一个TCP连接就在两个进程的套接字之间建立了。这条连接是全双工的,即连接双方的进程可以在此连接上同时进行报文的收发。当应用程序结束报文发送时,必须拆除该连接。

可靠数据传输服务指的是通信进程能够依靠TCP,无差错、按适当顺序交付所有发送的数据。当应用程序的一端将字节流传进套接字时,它能够依靠TCP将相同的字节流交付给接收方的套接字,而没有字节的丢失和冗余。

TCP还拥有拥塞控制机制。当发送方和接收方之间的网络出现拥塞时,TCP的拥塞控制机制会抑制发送进程,无论是客户还是服务器。

TCP和UDP都没有提供任何加密机制,即发送进程传进其套接字的数据与经网络传送到目的进程的数据相同,这就可能导致数据在两个进程间的中间链路被发现。为了解决安全问题,TCP的加强版本:安全套接字层(Secure Sockets Layer,SSL)应运而生。用SSL加强后的TCP不仅能做到传统的TCP可以做的一切,还提供了关键的进程到进程的安全性服务,包括加密、数据完整性和端点鉴别。SSL有它自己的套接字API,类似于传统的TCP的套接字API。当一个应用使用SSL时,发送进程向SSL套接字传递明文数据,发送主机中的SSL则加密该数据并将加密的数据传递给TCP套接字。加密的数据经因特网传送到接收进程中的TCP套接字,该接收套接字将加密数据传递给SSL,由其进行解密,最后SSL通过它的SSL套接字将明文数据传递给接收线程。

  • UDP服务

UDP时一种不提供不必要服务的轻量级运输层协议,它只提供最小服务。

UDP是无连接的,在两个进程通信前没有握手过程。

UDP协议提供一种不可靠数据传送服务,即当一个进程将一个报文发送进UDP套接字时,UDP协议不能保证该报文将到达接收进程,甚至到达了也可能是乱序的。

UDP没有拥塞控制机制,因此UDP的发送端可以用它选定的任何速率向其下层(网络层)注入数据。

应用层协议

前面介绍了网络进程间的相互通信通过将报文发送进套接字来实现,而报文的构造以及报文字段的含义就需要应用层协议来定义。应用层协议定义了运行在不同端系统上的应用程序进程如何相互传递报文,更详细的内容包括:

  • 交换的报文类型,例如请求报文和响应报文;
  • 各种报文类型的语法,例如报文中的各个字段以及这些字段的描述;
  • 字段的语义,即这些字段中的信息的含义;
  • 确定一个进程何时以及如何发送报文,对报文进行响应的规则等。

HTTP

Web的应用层协议是超文本传输协议(HyperText Transfer Protocol,HTTP),它是Web的核心。HTTP由两个程序实现:一个客户程序和一个服务器程序。客户程序和服务器程序运行在不同的端系统中,通过交换HTTP报文进行会话。HTTP定义了这些报文的结构以及客户和服务器进行报文交换的方式。

Web页面是由对象组成的。一个对象只是一个文件,例如一个HTML文件、一个JPG图片、一个视频片段这样的文件,并且它们都可以通过一个URL地址寻址。多数Web页面都含有一个HTML基本文件以及几个引用对象。HTML基本文件通过对象的URL地址引用页面中的其他对象。每个URL地址由两部分组成:存放对象的服务器主机名和对象的路径名。例如,URL地址http://www.csdn.net/file/upload/yanzu.jpg,www.csdn.net是主机名,而/file/upload/yanzu.jpg是路径名。Web浏览器实现了HTTP的客户端,Web服务器实现了HTTP的服务器端用于存储Web对象。

HTTP定义了Web客户向Web服务器请求Web页面的方式,以及服务器向客户传送Web页面的方式。HTTP使用TCP作为它的支撑运输层协议。

HTTP是一个无状态协议,即服务器不存储任何关于客户的状态信息。例如某个客户在短时间内连续请求服务器的同一个对象,服务器并不会因为刚为该客户提供了该对象就不做反应,而是重新发送该对象。

非持续连接和持续连接

在许多因特网应用程序中,客户和服务器在一个相当长的时间范围内通信,其中客户发出一系列请求并且服务器对每个请求进行响应。当这种客户-服务器的交互是经TCP进行的,那么请求以及响应的发送方式就有两种:一种是每个请求/响应对经一个单独的TCP连接发送,这种方式称为非持续连接;另一种方式是所有的请求/响应对都经相同的TCP连接发送,这种方式称为持续连接。HTTP默认情况下使用持续连接,但其也可以使用非持续连接。

  • 非持续连接的HTTP

在非持续连接的情况下,从服务器向客户传送一个包含10个JPEG图形的URL为“http://www.csdn.net/file/upload/hello.index”Web页面的步骤如下:

 1)HTTP客户端在端口号80发起一个到服务器的TCP连接,该端口号是HTTP的默认端口。在客户和服务器上分别有一个套接字与该连接相关联。

 2)HTTP客户经过它的套接字向服务器发送一个HTTP请求报文,请求报文中包含路径名/file/upload/hello.index。

 3)HTTP服务器进程经它的套接字接收该请求报文,从其存储器检索出对象www.csdn.net/file/upload/hello.index,在一个HTTP响应报文中封装对象,并通过其套接字向客户发送响应报文。

 4)HTTP服务器通知TCP断开该TCP连接,TCP确认客户已经完整地接收到响应报文后才会实际中断连接。

 5)对该Web页面引用的10个JPEG图形对象重复前四个步骤。

当浏览器收到Web页面后,以自己的方式向用户显示该页面。

在使用非持续连接时,每个TCP连接只传输一个请求报文和一个响应报文,因此,在上面的例子中要产生11个TCP连接。

一个短分组从客户到服务器然后再返回客户所花费的时间称为往返时间(Round-Trip Time,RTT)。RTT包括分组传播时延、分组在中间路由器和交换机上的排队时延以及分组处理时延。当用户点击一个超链接时,浏览器向服务器发起一个TCP连接,这涉及到一次“三次握手”的过程:客户向服务器发送一个小TCP报文段,服务器用一个小TCP报文段做出确认和响应,最后,客户向服务器返回确认。三次握手过程的前两次握手耗费的时间就是一个RTT。三次握手过程完成前两个部分后,客户结合三次握手的第三部分向该TCP连接发送一个HTTP请求报文,当该请求报文到达服务器,服务器就在该TCP连接上发送HTML文件。三次握手的第三部分和服务器的响应又耗费了一个RTT的时间。因此,总的响应时间就是两个RTT加上服务器传输HTML文件的时间。

  • 持续连接的HTTP

非持续连接的缺点很明显:1.必须为每一个请求的对象建立会维护一个新的TCP连接。2.每一个对象都要经受两倍RTT的交付时延,即第一个RTT用于创建TCP,第二个RTT用于请求和接收对象。

在采用持续连接的情况下,服务器在发送响应后保持该TCP连接打开。在相同的客户和服务器之间,后续的请求和响应报文能够通过相同的连接进行传送。在非持续连接中举的例子如果使用持续连接来传送,只需要单个持续TCP连接就可以。

HTTP报文格式

HTTP报文有两种:请求报文和响应报文。

  • HTTP请求报文

先来看一个典型的HTTP请求报文(打开百度随便搜了点什么,去除了一些首部行):

GET /s?ie=utf-8&mod=1&isbd=1&isid=ff15ff9f00027cf1&ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=hello&oq=hello&rsv_pq=ff15ff9f00027cf1&rsv_t=34dd1kFozKFfFd4ERemaAquqeLw7aweSuyzTzHIdldlZHd0zTqtHwmf68Gk&rqlang=cn&rsv_enter=0&rsv_dl=tb&rsv_btype=t&bs=hello&rsv_sid=undefined&_ss=1&clist=2f36dc8e3c97c2ce&hsug=&f4s=1&csor=5&_cr1=26788 HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36 Edg/86.0.622.69
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

其中第一行称为请求行,其后继的行叫做首部行。请求报有3个字段:方法字段、URL字段和HTTP版本字段。方法字段可以取多个值,包括GET、POST、HEAD、PUT和DELETE,本例中的方法是GET。URL字段是浏览器请求的对象。本例的HTTP版本是HTTP/1.1版本。

本例中从第二行开始到最后一行都是首部行。第二行的首部行Host指明了浏览器请求的对象所在的主机IP地址。第三行首部行Connection主要有两个取值:1.为close时表示服务器在发送完被请求的对象后就关闭这条连接,HTTP/1.0默认为此值。2.为keep-alive时表示客户端想要保持该连接为打开状态,HTTP/1.1默认为此值。第四行首部行User-agent用来指明用户代理,即向服务器发送请求的浏览器的类型,本例中的浏览器类型是Edge。最后一行的首部行Accept-language表示用户想要得到请求对象的语言版本,本例中zh-CN表示中文,即百度搜索的结果以中文显示。

请求报文的通用格式如下图:

请求报文中,当方法为GET时,实体体为空,使用POST方法时才使用该实体体。

  • HTTP响应报文

一个典型的HTTP响应报文如下:

HTTP/1.1 200 OK
Connection: CLOSE
Date: Sun, 22 Nov 2020 13:05:14 GMT
Server: Apache/2.2.3
Content-Type: test/html
(data data data)

该响应报文分为三个部分。其中,第一部分即为第一行,称为初始状态行;第二部分为第二行到第五行,称为首部行;最后一部分为最后一行,称为实体体。实体体部分是报文的主要部分,包含了所请求的对象本身。状态行有3个字段,分别为协议版本字段、状态码和相应状态信息。首部行除了以上几个还可以包括多个,此处暂时先介绍这几个。Connection:close首部行表示告诉客户,发送完该报文后将关闭该TCP连接。Date首部行表示服务器产生并发送该响应报文的日期和时间。Server首部行表示该报文是由一台Apache Web服务器产生的。Content-Type首部行表示实体体中的对象是HTML文本。

响应报文的通用格式如下:

其中常见的状态码及其对应的短语如下: 

状态行短语简介
200OK请求成功,信息在返回的响应报文中
301Moved Permanently请求的对象已经被永久转移了
400Bad Request通过差错代码,表示该请求不能被服务器理解
404Not Found被请求的文档不在服务器上
505HTTP Version Not Supported服务器不支持请求报文使用的HTTP协议版本

cookie

HTTP服务器是无状态的,这简化了服务器的设计。但有些Web站点需要识别用户,例如网站的推荐内容根据用户的身份不同而不同。为了解决这个问题,HTTP使用了cookie。

cookie技术有以下四个组件:

  1. 在HTTP响应报文中的一个cookie首部行;
  2. 在HTTP请求报文中的一个cookie首部行;
  3. 在用户端系统中保留有一个cookie文件,并由用户的浏览器进行管理;
  4. 位于Web站点的一个后端数据库。

cookie的工作过程如下:当我们使用一台电脑首次访问某网站,当请求报文到达服务器时,服务器将产生一个唯一识别码,并以此作为索引在它的后端数据库中产生一个表项;然后服务器用一个包含Set-cookie首部的HTTP响应报文对浏览器进行响应;当浏览器接收到该HTTP响应报文时,在它管理的cookie文件中添加包含该服务器的主机名和cookie识别码;在cookie过期之前,该浏览器发往该服务器的每个HTTP请求报文都包含一个包含识别码的Cookie首部行。

cookie可以用于标识一个用户,用户在首次访问一个站点时,可能需要提供一个用户标识。在后继会话中,浏览器向服务器传递一个cookie首部,从而向该服务器标识了用户,因此cookie可以在无状态的HTTP之上建立一个用户会话层。

Web缓存

Web缓存器(Web cache)也叫代理服务器(proxy server),是能够代表初始Web服务器来满足HTTP请求的网络实体。Web缓存器有自己的磁盘存储空间,并在存储空间中保存最近请求过的对象的副本。可以通过配置用户的浏览器,使得用户的所有HTTP请求首先指向Web缓存器。一旦某浏览器被配置,每个对某对象的浏览器请求首先被定向到该Web缓存器。例如,配置了Web缓存器的浏览器在向某个服务器发送请求时会发生以下步骤:

  1. 该浏览器创建一个到Web缓存器的TCP连接,并向Web缓存器中的对象发送一个HTTP请求;
  2. Web缓存器检查本地是否存储了该对象副本。如果有,则直接向客户浏览器返回包含了该对象的HTTP响应报文;
  3. 如果Web缓存器中没有该对象,则打开一个与该对象的厨师服务器(即客户浏览器最开始请求的服务器)的TCP连接。Web缓存器在这个TCP连接中发送对该对象的HTTP请求。收到该请求后,初始服务器向该Web缓存器发送具有该对象的HTTP响应报文。
  4. 当Web缓存器接收到该对象时,他在本地存储空间存储一份副本,并通过已有的客户浏览器到该Web缓存器的TCP连接向客户浏览器发送该副本。

Web缓存器既是服务器又是客户。当它接收浏览器的请求并发回响应时是一个服务器;当它向初始服务器发送请求并接收响应时,它是一个客户。在因特网上部署Web缓存器有以下两个好处:

  1. Web缓存器可以大大减少对客户请求的响应时间,尤其是当客户与初始服务器之间的瓶颈带宽远低于客户与Web缓存器之间的瓶颈带宽时更是如此。如果在客户与Web缓存器之间有一个高速连接,并且用户请求的对象都在Web缓存器上,那么该Web缓存器可以迅速将对象交付给用户。
  2. Web缓存器可以大大减少一个机构的接入链路到因特网的通信量。

条件GET方法

Web缓存器有诸多好处,但其也有局限性,例如无法保证其本地保存的对象副本是最新的。例如,浏览器首次向Web缓存器请求“name”对象,Web缓存器向初始服务器发送请求,初试服务器返回响应“吴彦祖”,Web缓存器保存该对象副本并向浏览器发送包含该对象的响应报文。过段时间,初始服务器中的“name”对象更新为"赵彦祖",Web缓存器返回的是"吴彦祖"呢还是"赵彦祖"呢?

如果返回"吴彦祖"那这个Web缓存器也太鸡肋了点。HTTP协议有一种机制,允许缓存器证实它的本地对象副本是否是最新的。这种机制就是条件GET方法。如果请求报文使用GET方法并且请求报文中包含一个"If-Modified-Since"首部行,则这个HTTP请求报文就是一个条件GET请求报文。

继续上面的例子,事实上,初始服务器在第一次返回"name"对象的HTTP响应报文会包含一个"Last-Modified"首部行,该首部行表示对象的最后修改日期。Web缓存器存储该对象副本时同样也存储了该对象的最后修改日期。过段时间,用户再次请求该对象时,由于该对象已经在Web缓存器上存有副本,但不知道是否是最新的,因此,该缓存器向初始服务器发送一个条件GET请求报文执行最新检查,该请求报文包含"If-Modified-Since"首部行,该首部行的值就是上一次Web缓存器存储的该对象的最后修改日期。该条件GET报文的含义在于告诉服务器,仅当自指定日期之后该对象被修改过,才返回该对象。例如Web缓存器第一次请求"name"对象的日期为2020年10月11号,则当客户再次请求该对象时,Web缓存器向初始服务器发送的条件GET报文中"If-Modified-Since"首部行的值就为2020年10月11号。假设该对象在2020年10月11号到现在修改过,则初始服务器返回该该对象的最新版本,Web缓存器更新该对象的副本并发送客户的响应报文;假设该对象并未修改过,则初始服务器向Web缓存器发送的响应报文中不会包含请求对象。

DNS:因特网的目录服务

因特网上的主机可以通过多种方式进行标识。其中一种方式是用它的主机名(hostname),例如www.baidu.com、www.csdn.net等。然而主机名几乎没有提供关于主机在因特网中位置的信息,并且主机名可能由不定长的字母数字构成,路由器难以处理。因此除了使用主机名,还可以使用IP地址进行标识。一个IP地址由4个字节组成,并且有着严格的层次结构。例如127.0.0.1这样的IP地址,其中的每个字节都被句点分割开来,表示了0~255的十进制数字。当我们从左到右扫描一个IP地址时,会得到越来越具体的关于主机位置信息。

对于人们来说,主机地址比较好记忆,而路由器则更好的处理定长的、有层次结构的IP地址。因此因特网提供了一种能进行主机名到IP地址转换的目录服务,即域名系统(Domain Name System,DNS)。DNS既是一个由分层的DNS服务器实现的分布式数据库,又是一个能使得主机查询分布式数据库的应用层协议。

DNS通常是由其他应用层协议使用的,例如HTTP、SMTP和FTP,用于将用户提供的主机名解析为IP地址。例如当用户在浏览器访问www.csdn.net/yanzu.html时,为了使用户的主机能够将HTTP请求报文发送到Web服务器上,就必须要先获得Web服务器的IP地址。通过主机名获取IP地址的步骤如下:

  1. 用户主机上运行DNS应用的客户端;
  2. 浏览器从URL中抽出主机名www.csdn.net,将此主机名传给DNS客户端;
  3. DNS客户端向DNS服务器发送一个包含主机名的请求;
  4. DNS客户端收到回答报文,其中含有对应该主机名的IP地址;
  5. 浏览器收到来自DNS的IP地址,最后向位于该IP地址80端口的HTTP服务器发起一个TCP连接。

DNS除了进行主机名到IP地址的转换外,还提供了一些其他的重要服务:

  • 主机别名:有些主机的主机名可能比较复杂,为了便于记忆,它还可以有多个别名。此时它原本的复杂主机名称为规范主机名。应用程序可以调用DNS来获得主机别名对应的规范主机名以及主机的IP地址。
  • 邮件服务器别名:与主机别名类似,电子邮件应用程序可以调用DNS,对提供的主机别名进行解析,以获得该主机的规范主机名以及IP地址。
  • 负载分配:DNS也用于在冗余的服务器直接进行负载分配。繁忙的站点被冗余分布在多台服务器上,每台服务器均运行在不同的端系统上,每个都有着不同的IP地址。由于这些冗余的Web服务器,一个IP地址集合与同一个规范主机名相联系。DNS数据库中存储着这些IP地址集合,当客户对映射到某地址集合的名字发出一个DNS请求时,该服务器用IP地址的整个集合进行响应,但在每个回答中循环这些地址次序。因为客户总是向IP地址排在最前面的服务器发送HTTP请求报文,所以DNS就在这些冗余的Web服务器直接循环分配了负载。

DNS工作机理概述

DNS工作过程总结如下:运行在用户主机的某些应用程序需要将主机名转换为IP地址,因此它们调用DNS的客户端,并指明需要被转换主机名。主机DNS客户端接收到后,使用UDP数据报经端口53发送一个DNS查询报文。经过若干秒的时延后,用户主机上的DNS客户端接收到一个提供了映射结果的DNS回答报文,然后此映射结果被传递到调用DNS的应用程序。从用户主机调用应用程序的角度看,DNS只是一个提供简单、直接的转换服务的黑盒子。事实上,它由分布于全球的大量DNS服务器以及定义了DNS服务器与查询主机通信方式的应用协议组成。

DNS最简单的设计是在因特网上只使用一个DNS服务器,该服务器包含了所有主机的映射。在这种集中式设计中,客户直接将所有查询请求发往唯一的DNS服务器,该服务器响应所有查询客户。但如今的因特网有着数量巨大的主机,这种集中式设计就有不少问题,事实上所有访问量较大的网站都不适合采用集中式设计,集中式设计包含如下问题:

  1. 单点故障(a single point of failure):如果该DNS服务器崩溃,整个因特网将随之瘫痪。
  2. 通信容量(traffic volume):单个DNS服务器要处理所有的DNS查询,意味着要为上亿台主机产生的所有HTTP请求报文和电子邮件报文服务,明显通信容量不能支撑这么多请求。
  3. 远距离的集中式数据库(distant centralized database):单个DNS服务器不可能对所有查询客户来说是“邻近”的,因此仅仅物理距离将导致严重的时延。
  4. 维护(maintenance):单个DNS服务器不能不为所有的因特网主机保留记录,这将使中央数据库越来越庞大,并且还要为不断频繁添加的主机更新。

基于以上原因,DNS采用了分布式的设计方案。

DNS使用了大量的DNS服务器,它们以层次方式组织,并分布在全世界范围内。没有一台DNS服务器拥有因特网上所有主机的映射。这些服务器大致分为以下3种:根DNS服务器、顶级域(Top-Level Domain,TLD)DNS服务器和权威DNS服务器。当客户想要查询www.baidu.com的IP地址,将发生以下事件:客户首先与根服务器之一联系,根服务器返回顶级域名com的TLD服务器的IP地址。然后客户与这些TLD服务器之一联系,TLD服务器返回baidu.com的权威服务器IP地址。最后,客户与baidu.com权威服务器之一联系,权威服务器返回www.baidu.com的IP地址给客户。这3类服务器的层次结构如下:

  • 根DNS服务器:在全世界有多台根DNS服务器,这些根DNS服务器由不同的组织管理。根DNS服务器提供TLD服务器的IP地址。
  • 顶级域(TLD)服务器:对于每个顶级域(如com、org、edu、net和gov)和所有国家的顶级域(如cn、uk、fr),都有TLD服务器或服务器集群。TLD服务器提供了权威DNS服务器的IP地址。
  • 权威DNS服务器:在因特网上具有公共可访问主机(如Web服务器和邮件服务器)的每个组织机构必须提供公共可访问的DNS记录,这些记录将这些主机的名字映射为IP地址。该组织机构可以选择实现它自己的权威DNS服务器以保存这些记录,也可以支付费用让这些记录存储在某个服务提供商的一个权威DNS服务器中。

DNS缓存

如果一个用户想要知道某个主机名的IP地址,需要以下步骤:

  1. DNS客户端发送查询报文到本地DNS服务器;
  2. 本地DNS服务器转发该报文到根DNS服务器;
  3. 根DNS服务器返回TLD服务器IP地址列表给本地DNS服务器;
  4. 本地DNS服务器向TLD服务器之一发送查询报文;
  5. TLD服务器返回权威DNS服务器IP地址进行响应,该权威DNS服务器是邻近目的主机地址的服务器;
  6. 本地DNS服务器向权威DNS服务器发送查询报文;
  7. 权威DNS服务器返回目的主机名的IP地址映射;
  8. 本地DNS服务器返回DNS客户端IP地址映射。

也就是说,用户查询一个主机名的IP地址的过程总共发送了8次DNS报文,有的时候TLD服务器不一定能返回权威服务器的IP地址,可能它只知道某个中间服务器的IP地址,这种情况发送的DNS报文数量更多。为了改善时延性能并减少在因特网上到处传输的DNS报文数量,DNS广泛使用了缓存技术。

DNS缓存的原理很简单,当某台DNS服务器接收到一个DNS回答时,他会将映射缓存道本地存储器中。但由于主机和主机名与IP地址间的映射并不是永久的,因此DNS服务器在一段时间后将丢弃缓存信息。

 

应用层中关键的还有套接字编程,但其中涉及到TCP和UDP的知识,因此笔者觉得在学习完《计算机网络:自顶向下的方法》这本书后结合《Java网络编程》这本书更深入的了解套接字编程相关API。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值