• 计算机网络二:应用层


    一、应用与应用层协议

    前面提到过,因特网是分布式网络应用的平台,作为为应用提供服务的联网基础设施。那么什么是网络应用呢?网络应用又是怎么使用因特网作为基础设置的呢?

    研发网络应用的程序的核心是写出能够运行在不同的端系统和通过网络彼此通信的程序。

    1. 网络应用程序体系结构

    前面学到的5层因特网分层结构,可以称之为网络的体系结构,从应用程序开发人员来看,网络体系结构是固定的,它为应用程序提供了特定的服务集合。

    从程序运行的端系统角度看,应用程序开发者更为关注的是应用程序体系结构。主流的应用程序体系结构分为两种:客户-服务器体系和对等(P2P)体系结构

    A. 客户-服务器体系:

    • 包含客户和服务器两个角色,总是打开的主机称为服务器,它服务于客户主机的请求。
    • 客户之间不直接通信,只与服务器直接通信
    • 服务器具有固定的、周知的地址,改地址称为IP地址
    • 当今的应用中,为了更高效地处理更多的请求,产生了配置大量主机的数据中心,用于创建强大的虚拟服务器
    • 常见的应用包括:Web、FTP、Telnet和电子邮件

    B. P2P体系结构:

    • 对于数据中心的专用服务器有最小的(或者没有)依赖,应用程序在间断连接的的主机对之间使用直接通信,这些主机对称为对等方
    • 自扩展性:以P2P文件共享应用为例,尽管每个对等方都由于请求文件产生工作负载,但每个对等方通过向其他对等方分发文件也为系统增加服务能力
    • 常见的应用包括:文件共享(例如BitTorrent)、对等方协助下载加速器(例如迅雷)、因特网电话和视频会议(例如Skype)

    2. 进程通信

    前面提到应用需要在不同端系统上运行程序,实际上程序是静态的,真正运行的是进程,可以理解为进程是程序的运行时,进行通信的实际上是进程,而不是程序

    当多个进程运行在相同的端系统上时,它们使用进程间通信机制进行通信,这里不涉及网络。对于两个不同端系统上的进程,需要跨越计算机网络交换报文来进行通信。

    客户和服务器进程

    • 无论是客户-服务器体系,还是P2P体系结构,在每对通信进程中都存在客户进程和服务器进程
    • 在一对进程之间的通信会话场景中,发起通信的进程被标识为客户,在会话开始时等待联系的进程是服务器

    套接字

    • 进程之间的通信必须通过下面的网络,而实际上进程是通过套接字向网络发送报文和从网络接收报文
    • 套接字是同一台主机内应用层和运输层之间的接口,该套接字是建立网络应用程序的可编程接口,也被称为应用程序和网络之间的应用程序编程接口
    • 应用程序开发者可以控制在应用层端的一切,但是对套接字的运输层几乎没有控制权,可能的控制权仅限于:①选择传输层协议;②也许能设定几个运输层参数

    进程寻址

    • 进程之间的通信也需要具体的地址(目的地),标识该地址需要两种信息:①主机的地址;②目的主机接收进程的标识符
    • 主机地址用IP地址标识,而目的主机接收进程用端口号标识,常见的应用已经分配了具体的端口号,如Web服务器端口号为80

    3. 运输服务

    进程之间通过套接字传输报文,套接字之下是运输层,对于运输层,能够为应用程序提供的运输服务包括:可靠数据传输、吞吐量、定时和安全性

    • 可靠数据传输
      • 由应用程序的一端发送的数据可以正确、完全地交付给应用程序的另一端,称为可靠数据传输
      • 容忍丢失的应用:可以承受一定量的数据丢失的引用,如交谈时音频/视频
    • 吞吐量
      • 发送进程能够向接收进程交付比特的速率称为吞吐量
      • 带宽敏感的应用:具有吞吐量要求的应用
      • 弹性应用:能够根据当时可用的带宽或多或少地利用可供使用的吞吐量的应用
    • 定时
      • 如:发送方注入套接字的每个比特到达接收方的套接字不超过特定时间
    • 安全性
      • 如:在发送主机中,运输协议能够加密由发送进程传输的所有数据,在接收主机中,运输层协议能够将数据交付给接收进程之前解密这些数据

    以上是运输层理论上可以提供的运输服务,而应用程序是通过选择特定的运输层协议,从而能够享受这些运输服务的。

    因特网提供的运输层协议有两个:TCP和UDP

    TCP协议

    • TCP协议可以提供的服务包括:面向连接服务、可靠数据传输服务
      • 面向连接服务:应用传输报文之前,先通过握手建立TCP连接,该连接是全双工的,连接双方的进程可以同时进行报文收发
      • 可靠数据传输服务:TCP可以无差错、按适当顺序交付所有发送的数据
    • TCP还具有拥塞控制机制,当发送方和接收方之间的网络出现拥塞,TCP可以抑制发送进程
    • 通过强化TCP产生的安全套接字(SSL) 可以保证安全性,SSL不是与TCP、UDP同层次的第三种因特网运输协议,它是在应用层上对TCP的强化

    UDP协议

    • 仅提供最小服务
    • 无连接、不可靠数据传输,不保证报文的到达以及有序
    • 没有拥塞控制机制,可以用选定的任意速率向下一层(网络层)注入数据

    通过因特网提供的仅有的两个运输层协议来看,我们期望运输层所能提供的服务,即可靠数据传输、吞吐量、定时和安全性,并没有完全被实现,如吞吐量、定时等。实际上,这些遗漏的服务目前的因特网并没有提供,而是通过将应用设计成尽最大可能对付这种保证缺失

    4. 应用层协议

    进程之间通过将报文发送进套接字实现网络进程之间的通信,而应用层协议定义了运行在不同端系统上的应用程序进程如何相互传递报文

    具体的,应用层协议定义了:

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

    应用层协议 & 应用:
    应用层协议是应用的一部分,而且是非常重要的一部分。一个应用,如Web引用,它包括文档格式的标准(即HTML)、Web浏览器、Web服务器以及一个应用层协议(HTTP协议)

    二、Web应用和HTTP协议

    1. 概况

    Web应用概述:

    • Web网页是由对象组成的,而一个对象只是一个文件,如:一个HTML文件、一个JPEG图片、一个Java小程序或一个视频片段,它们都可通过一个URL地址寻址。
    • HTML文件通过对象的URL地址引用页面中的其他对象,每个URL地址包含两部分:存放对象的服务器主机名和对象的路径名。例,http://www.someSchool.edu/someDepartment/picture.gif,www.someSchool.edu是主机名,/someDepartment/picture.gif是对象的路径名
    • Web应用属于客户-服务器体系,其中Web浏览器作为客户端,Web服务器作为服务器端。

    超文本传输协议(HTTP)概述:

    • HTTP使用TCP作为运输层协议
    • HTTP是无状态协议,服务器向客户发送被请求的数据,但是不会存储任何该用户的状态信息

    2. 非持续连接和持续连接

    非持续连接:每个请求/响应对是经一个单独的TCP连接发生
    持续连接:所有的请求及其响应经过相同的TCP连接发生

    HTTP既可以使用非持续连接,也可以使用非持续连接,默认使用持续连接

    非持续连接的缺点:

    • 必须为每一个请求的对象建立和维护一个全新的连接,为Web服务器带来了严重的负担
    • 每个对象经受两倍RTT的交付时延
      • 往返时延(Round-Trip Time, RTT):一个短分组从客户到服务器然后再返回客户所花费的时间,包含传播时延、排队时延以及分组处理时延等

    HTTP1.1持续连接的情况下,服务器在发送响应后保持该TCP连接打开,在相同的客户与服务器之间,后续的请求和相应报文能够通过相同的连接进行传送。
    HTTP/2中,允许相同连接中多个请求和回答交错,并增加了该连接中优化HTTP报文请求和回答的机制

    3. HTTP报文格式

    HTTP报文分为:请求报文和响应报文。

    请求报文

    通用的请求报文格式包括:请求行、首部行和实体体
    HTTP请求报文通用格式

    以下是一个典型的HTTP请求报文:

    GET /somedir/page.html HTTP/1.1
    Host: www.someshcool.edu
    Connection: close
    User-agent: Mozilla/5.0
    Accept-language: fr
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中,第一行称为请求行,包含三个字段:方法字段、URL字段和HTTP版本字段。方法字段包括:GET、POST、HEAD、PUT、DELETE。/somedir/page.html为对象的URL。浏览器实现的是HTTP/1.1版本。

    余下的称为首部行。

    • www.someshcool.edu代表对象所在的主机;
    • Connection: close表示告诉服务器不需要使用持续连接;
    • User-agent: 用于指明用户代理,即浏览器类型,Mozilla/5.0表示Firefox浏览器;
    • Accept-language: fr表示希望得到对象的法语版本

    上述例子中,由于使用GET方法,实体体为空,而在使用POST方法时才使用实体体。

    响应报文

    通用的请求报文格式包括:状态行、首部行和实体体

    HTTP响应报文通用格式

    以下是一个HTTP响应报文:

    HTTP/1.1 200 OK
    Connection: close
    Date: Tue, 18 Aug 2015 15:44:04 GMT
    Server: Apache/2.2.3 (CENTOS)
    Last-Modified: Tue, 18 Aug 2015 15:11:03 GMT
    Content-Length: 6821
    Content-Type: text/html
    
    (data data data data data data...)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    第一行为状态行,包含三个字段:协议版本字段、状态码和相应状态信息

    对于状态码,常见的状态码和状态信息包括:

    • 200 OK:请求成功,信息在返回的响应报文里
    • 301 Moved Permanently:请求的对象已经被永久转移。新的URL在响应报文的Location首部行中
    • 400 Bad Request:一个通用差错代码,表示请求不能被服务器理解
    • 404 Not Found:被请求的文档不在服务器上
    • 505 HTTP Version Not Supported:服务器不支持请求报文使用的HTTP协议版本

    以上响应报文中,首部行有6个:

    • Connection: close告知客户,发送完报文后关闭TCP连接;
    • Date: 表示服务器产生并发送该响应报文的时间,也即服务器从它的文件系统中检索到该对象,将该对象插入报文并发送该报文的时间
    • Server:表示报文由一台Apache Web服务器产生
    • Last-Modified: 表示对象创建或者最后修改的时间
    • Content-Length: 表示对象的字节数
    • Content-Type: 表示对象时html文本

    4. cookie

    前面提到,HTTP协议是无状态的,服务器不会存储任何该用户的状态信息。但是在一个Web站点,通常希望能够识别用户,可能是因为服务器希望限制用户的访问,或者因为它希望把内容与用户身份联系起来。这是就需要用到cookie对用户进行追踪。

    cookie技术有四个组件:

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

    通过cookie字段,Web站点可以实现标识用户,从而在无状态的HTTP之上建立一个用户会话层。

    5. Web缓存器

    Web缓存器,又称代理服务器,是能够代表初始服务器来满足HTTP请求的网络实体。

    Web缓存器有自己的磁盘存储空间,并在存储空间中保存最近请求过的对象的副本。通过配置用户浏览器,可以使得用户的所有HTTP请求首先指向Web缓存器。当请求在Web缓存器中命中,直接返回请求对象;否则,由Web缓存器再向初始服务器请求对象并返回给用户,请求对象在Web缓存中存储副本。

    Web缓存器即使服务器又是客户,当接受浏览器的请求并返回响应时是一个服务器;当向初始服务器发送请求并接受响应时是一个客户。

    部署Web缓存器的好处有:

    • Web缓存器可以大大减少对客户请求的响应时间,尤其是当客户与初始服务器之间的瓶颈带宽远低于客户与Web缓存器之间的瓶颈带宽
    • Web缓存器可以大大减少一个机构的接入链路到因特网的通信量

    6. 条件GET方法

    使用Web缓存器可以带来诸多好处,但是也引入了一个新的问题,即存放在Web缓存器中的对象副本可能是陈旧的,在初始服务器上的对象可能已经被修改了。

    为了解决这个问题,HTTP协议引入了条件GET方法。条件GET方法有以下特征:

    • 请求报文使用GET方法
    • 请求报文中包含一个"if-Modified-Since"首部行

    当Web缓存器向初始服务器请求一个对象时,初始服务器会通过报文返回该对象,同时首部行中包含Last-Modified,Web缓存器存储对象副本以及最后修改时间。当过了一段时间,用户请求该对象,Web缓存器会发送条件GET报文,if-Modified-Since首部行的值即为上次Last-Modified的值。当初始服务器收到报文后,检查对象是否自if-Modified-Since有修改过,如果修改过则返回最新对象,没有修改也会发送一个响应报文,但是报文中不包含对象。

    三、电子邮件和SMTP协议

    1. 概况

    电子邮件系统主要组成部分包括:用户代理、邮件服务器和简单邮件传输协议(SMTP)

    • 用户代理:用户在自己的端系统上运行用户代理程序,从而可以阅读、回复、转发、保存和撰写报文,微软的Outlook和Apple Mail就是典型的电子邮件用户代理
    • 邮件服务器:存储和发送邮件报文
      • 邮箱:每个接收方都会在其对应的邮件服务器上有一个邮箱
      • 报文队列:当A邮件服务器无法将邮件发送给B邮件服务器时,邮件会存储在A邮件服务器的报文队列中并在以后继续尝试发送
    • SMTP协议:电子邮件中主要的应用层协议,使用TCP可靠数据传输,从发送方的邮件服务器向接收方的邮件服务器发送邮件

    因特网电子邮件系统

    2. SMTP协议

    SMTP一般不使用中间邮件服务器发送邮件,即使这两台服务器位于地球两端也是如此。

    客户SMTP在与服务器SMTP建立TCP连接后,将会执行某些应用层的握手,相当于人类在互相交流前的自我介绍。彼此介绍之后,客户端才发送报文。如下所示为SMTP客户 ©和SMTP服务器(S)之间的应用层握手示例,其中客户的主机名为crepes.fr,服务器的主机名为:hamburger.edu。

    S: 220 hamburger.edu
    C: HELO crepes.fr
    S: 250 Hello crepes.fr, pleased to meet you
    C: MAIL FROM: 
    S: 250 alice@crepes.fr ... Sender OK
    C: RCPT TO : 
    S: 250 bob@hamburger.edu ... Recipent OK
    C: DATA
    S: 354 Enter Mail, end with "." on a line by itself
    C: Do you like ketchup
    C: How about pickles
    C: .
    S: 250 Message accepted for delivery
    C: QUIT
    S: 221 hamburger.edu closing connection
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    SMTP vs HTTP
    相同点:SMPT和持续的HTTP都是用持续连接
    不同点:

    • HTTP是一个拉协议,TCP连接是由想接收文件的机器发起的;而SMTP是一个推协议,TCP连接是由要发送文件的机器发起的
    • SMTP限制所有报文的体部分(不只是首部)只能采用简单的7比特ASCII表示,对于大的图片、声音、视频文件,需要在传送前将二进制多媒体数据编码为ASCII,传输后再还原为多媒体数据;HTTP数据不受这种限制
    • 对于既包含文本又包含图片(或其他媒体类型)的文档,HTTP会将每个对象封装到它自己的HTTP响应报文中,而SMTP则将所有对象放在一个报文中

    SMTP报文格式
    SMTP报文格式包含:首部行、报文体,首部行与报文体之间是空白行。每个首部必须含有一个From:首部行和To:首部行,其他首部行可选。
    以下是一个典型的报文首部

    From: alice@crepes.fr
    To: bob@hamburger.edu
    Subject: Serching for the meaning of lifr
    
    
    • 1
    • 2
    • 3
    • 4

    3. 几个思考问题

    前面提到了因特网电子邮件系统的整体组成,现在我们来思考几个问题:

    问题1:为什么要有用户代理,发送方和接收方在自己的PC上放置邮件服务器不好吗?这样彼此之间可以直接进行对话

    • 如果这样设计,那么接收方为了能够及时接受在任何时候到达的新邮件,他的PC必须总是运行着并一直保持在线,这样是不现实的
    • 典型的场景,是用户在本地PC上运行一个用户代理程序,而用户代理访问存储在总是保持开机的共享邮件服务器上的邮箱

    问题2: 发送方PC运行用户代理,为什么该用户代理不直接通过SMTP协议直接与接收方对应的邮件服务器通信?而是要先将报文发送到自己对应的邮件服务器上,再由该邮件服务器与接收方的邮件服务器进行通信?

    • 实际上SMTP是支持将邮件从发送方的用户代理直接传送到接收方对应的邮件服务器的
    • 但是如果不通过发送方对应的邮件服务器,发送方的用户代理将没有办法到达一个不可达的目的地接收服务器。如,接收方的邮件服务器暂时未运行,邮件可以存储在发送方的邮件服务器中,并重复尝试发送直到接收方的邮件服务器运行

    4. 邮件访问协议

    结合之前学到的,SMTP是一个推协议,结合电子邮件系统的结构,SMTP既可以用来将邮件从发送方的邮件服务器传输到接收方的邮件服务器,也可以用来将邮件从发送方的用户代理传送到发送方的邮件服务器

    那么问题来了,作为接收方,如何通过用户代理获取对应服务器上的邮件呢?要知道取邮件是一个拉的操作,而SMTP是一个推协议,因此不能用SMTP来实现。

    基于这种情况,就需要用到邮件访问协议,目前流行的包括:第三版的邮局协议(POP3)、因特网邮件访问协议(IMAP)和HTTP

    4.1. POP3协议

    该协议非常简单,也因此功能相当有限。POP3按照三个阶段进行:特许、事务处理以及更新

    特许

    • 用户代理发送用户名和口令以鉴别用户
    • 包含两个主要的命令:user pass

    事务处理

    • 用户代理取回报文,同时还可以对报文作删除标记、取消报文删除标记以及获取邮件的统计信息等操作
    • 该过程中用户代理会发出一些命令,服务器的汇报有两种:+OK用于指示前面的命令是正常的;-ERR用于指示前面的命令出现了差错

    更新

    • 出现在客户发送了quit命令之后,目的是结束POP3会话
    • 邮件服务器会删除被标记为删除的报文

    下载并删除 vs 下载并保留

    • 下载并删除,用户代理会发出list(列出所有存储报文的长度)、retr(取回邮件)和dele(删除邮件)命令
    • 下载并保留,用户代理下载某邮件后,该邮件仍保留在邮件服务器上
    • 下载并保留的方式,才能实现在不同机器上都能访问到同一个邮件

    在用户代理和邮件服务器之间的POP3会话期间,服务器会保留一些状态信息,但是并不会在会话过程中携带状态信息

    4.2. IMAP协议

    POP3协议是通过将邮件下载到本地主机,而没有给用户提供任何创建远程文件夹并为报文指派文件夹的方法

    IMAP协议为用户提供了创建文件夹以及将邮件从一个文件夹移动到另一个文件夹的命令,同时还为用户提供了在远程文件夹中查询邮件的命令

    IMAP服务器还维护了会话的用户状态信息

    IMAP协议另一个特性是,它具有允许用户代理获取报文某些部分的命令。如只读取报文的首部,这在用户代理与邮件服务器之间使用低带宽连接时非常有用

    4.3. HTTP协议
    • 使用该协议时,用户代理就是普通的浏览器,用户和远程邮箱之间的通信通过HTTP进行
    • 收件人从邮箱获取邮件使用的是HTTP,发送人将邮件发送给邮件服务器用的也是HTTP,而不再是SMTP。

    四、DNS

    人类可以用很多方法进行标识,比如出生证明上的姓名、社会保险号、驾照上的号码等等。而主机同样有很多标识方法,常见的有主机名和IP地址,主机名便于记忆,但是几乎没有提供关于主机在互联网中位置的信息;IP地址可以表示主机位置,但是又不方便记忆。DNS提供了主机名到IP地址的转换

    1. DNS提供的服务

    域名系统(Domain Name System, DNS)是:

    • 一个分层的DNS服务器实现的分布式数据库
    • 一个使得主机能够查询分布式数据库的应用层协议

    DNS服务器通常是运行在BIND软件的UNIX机器,DNS协议运行在UDP之上

    除了前面提到的提供了主机名到IP地址的转换,DNS还提供以下服务:

    • 主机别名:拥有主机名的主机还可以拥有一个或多个别名,这种情况下,主机名也称为规范主机名。别名会比规范主机名更方便记忆。
    • 邮件服务器别名:邮件服务器的主机,同样可以有别名。一个公司的邮件服务器和Web服务器可以使用相同的主机别名。
    • 负载均衡:存在冗余的服务器情况下,这些服务器每台都运行在不同的端系统上,各自有不同的IP地址。此时一个IP地址集合对应同一个规范主机名,用户发送DNS请求,DNS会在这些IP地址之间循环分配负载。

    2. DNS工作机理

    就提供主机名到IP地址的转换服务而言,从用户主机调用应用程序来看,DNS是一个提供简单、直接的转换服务的黑盒子。

    DNS最简单的设计思路是,在因特网上只使用一个DNS服务器,所有的映射关系都包含在该服务器中。这样会带来以下的问题

    • 单点瘫痪:该DNS服务器奔溃,整个因特网都会瘫痪
    • 通信容量:单个DNS服务器需要应对所有的DNS服务
    • 远距离的集中式数据库:单个服务器无法邻近所有的查询客户,经常需要经过低速和拥塞链路
    • 维护:单个DNS服务器存储所有映射关系,数据库庞大,同时需要为每个新增的主机频繁更新

    实际中的DNS是一个在因特网上实现的分布式、层次数据库

    2.1. 分布式、层次数据库

    DNS存在三种类型的DNS服务器,分别是:根DNS服务器、顶级域(Top-Level Domain, TLD)DNS服务器和权威DNS服务器,没有一台DNS服务器拥有因特网上所有主机的映射。

    DNS服务器的层级结构

    根DNS服务器

    • 有400多个根服务器遍布世界
    • 提供TLD服务器的IP地址

    顶级域(Top-Level Domain, TLD)DNS服务器

    • 每个顶级域(如com, org, net, edu和gov等)和所有国家的顶级域(如ul, fr, ca和jp),都有对应的TCL服务器(或服务器集群)
    • 提供权威DNS服务器的IP地址

    权威DNS服务器

    • 在因特网上具有公共可访问主机的每个组织机构必须提供公共可访问的DNS记录,这些DNS记录记录在该组织的权威DNS服务器中
    • 一个机构可以选择自己实现权威DNS服务器,也可以付费将记录存储在服务提供商的一个权威DNS服务器中

    除此之外,还有一类称为本地DNS服务器,一般每个ISP(如一个居民区的ISP或一个机构的ISP)都有一台本地DNS服务器,当用户主机发出DNS请求时,该请求被发送给本地DNS服务器,它起着代理的作用,并将该请求转发到DNS服务器层次结构中。

    2.2. DNS缓存

    DNS缓存用于改善时延,并减少DNS的报文数量。

    在一个请求链中,当某DNS服务器接收到一个DNS回答(例如,包含主机名到IP地址的映射)时,它能将映射缓存到本地储存器中。下次遇到相同的请求可以直接返回结果。

    为了保持记录的实时性,DNS服务器在一段时间后(通常设置为2天)将丢弃缓存的信息。

    3. 记录和报文

    3.1. 资源记录

    实现DNS分布式数据库的所有DNS服务器存储的实际上是资源记录(Resource Record, RR),资源记录是一个4元组:(Name, Value, Type, TTL)

    • TTL是记录的生存时间,Name和Value则取决于Type
    • 当Type=A时,则Name是主机名,Value是主机名对应的IP地址,如:(relay1.bar.foo.com, 145.37.93.126, A)
    • 当Type=NS时,则Name是个域(如foo.com),Value是个知道如何获取该域中主机IP地址的权威DNS服务器主机名,如:(foo.com, dns.foo.com, NS)
    • 当Type=CNAME时,则Value是别名为Name的主机的规范主机名,如:(foo.com, relay1.bar.foo.com, CNAME)
    • 当Type=MX时,则Value是别名为Name的邮件服务器的规范主机名,如:(foo.com, mail.bar.foo.com, MX)

    如果一台DNS服务器是用于某特定主机名的权威DNS服务器,该服务器会有一条包含用于该主机名的类型A记录,如(relay1.bar.foo.com, 145.37.93.126, A)

    如果一台DNS服务器不是用于某特定主机名的权威DNS服务器,是顶级域DNS服务器,该服务器将包含一条类型NS的记录,对应包含某特定主机名的域,如(umass.edu, dns.umass.edu, NS);还将包含一条类型A的记录,对应包含NS记录中Value字段的DNS服务器IP地址,如( dns.umass.edu, 128.119.40.111,A)

    3.2. DNS报文

    DNS协议只有查询和回答两种报文,且这两种报文有着相同的格式

    DNS报文格式

    • 前12个字节是首部区域,标识符字段用于标识该查询,标志字段包含若干标志,后四个有关数量的字段指出了后面4类数据区域出现的数量
    • 问题区域包含:1. 名字字段,包含正在被查询的主机名字;2. 类型字段,指出有关该名字的正被询问的问题类型,如类型A、类型MX
    • 回答区域包含对最初请求的名字的资源记录,在该区域可以包含多条RR
    • 权威区域包含了其他权威服务器的记录
    • 附加区域包含了其他有帮助的记录
    3.3. DNS数据库插入记录

    前面提到DNS是一个分布式、分层的数据库,那数据库中的数据最初是怎么进入数据库的呢?

    假设需要有一个新的创业公司,公司名为Network Utopia,该公司需要付费让注册登录机构登记机构注册域名networkutopia.com。注册登录机构会验证该域名的唯一性,并将该域名输入DNS数据库。

    具体的,在注册该域名时,该公司需要向注册登录结构提供基本和辅助权威DNS服务器的名字和IP地址,对这两个权威DNS服务器的每一个,该注册登记结构确保将一个类型NS和一个类型A的记录输入TLD com服务器

    同时,还需要将用于Web服务器www.networkutopia.com的类型A资源记录和用于邮件服务器mail.networkutopia.com的类型MX资源记录输入权威DNS服务器

    完成以上步骤,就可以访问该公司的Web站点,并向公司的雇员发送电子邮件。

    五、P2P文件分发

    前面提到的应用(Web、电子邮件和DNS)都采用的客户-服务器体系,该体系极大依赖于总是打开的基础设施服务器。

    P2P体系结构则对基础设施基础具有最小(或者没有)依赖,而是成对间歇连接的主机(称为对等方)彼此直接通信。

    以文件分发为例,客户-服务器体系中,服务器需要向每个主机发送文件的一个副本,而P2P体系结构中,这些主机(对等方)能够向其他主机(对等方)重新分发它已经收到的该文件的任何部分,从而协助服务器。

    1. P2P体系结构的扩展性

    还是以文件分发为例,服务器和对等方使用接入链路与因特网相连,并定义:

    • us表示服务器接入链路的上载速率
    • ui表示第i对等方接入链路的上载速率
    • di表示第i对等方接入链路的下载速率
    • F表示被分发文件的文件长度
    • N表示对等方的数量

    分发时间是所有N个对等方得到该文件的副本所需要的时间,以分发时间衡量文件分发的速度。

    同时假设:因特网核心有足够的带宽,也因此所有的瓶颈都在网络接入链路。服务器和客户没有参与任何其他网络应用。

    文件分发示意图

    对于客户-服务器体系:

    • 服务器需要向N个对等发的每个传输一个文件的副本,分发的时间为:NF/us
    • dmin表示具有最小下载速率的对等方的下载速率,则最小分发时间至少为F/dmin
    • 因此,分发时间Dcs ≥ max{NF/us, F/dmin}

    对于P2P体系结构:

    • 为了使对等方能够得到文件,服务器必须经过接入链路至少发送该文件一次,分发时间至少为:F/us
    • dmin表示具有最小下载速率的对等方的下载速率,同样有最小分发时间至少为F/dmin
    • 系统的总上载能力为服务器的上载速率加上每个单独的对等方的上载速率,utotal=us+∑ui。同时系统必须交付NF比特,因此最小分发时间为:Dp2p ≥ max{F/us, F/dmin, NF/(us+∑ui)}

    设置F/u=1小时,us=10u,dmin≥us,则有:
    分发时间示意图

    2. BitTorrent

    BitTorrent是一个用于文件分发的P2P协议

    相关概念:

    • 洪流:参与文件分发的所有对等方的集合
    • :洪流中的对等方下载等长度的文件块,长度为256KB
    • 一个对等方加入洪流时没有块,随着时间流逝逐渐积累块。它在下载块的同时也在为其他对等方上传块。一旦获得整个文件,它可能离开洪流或继续为其他对等方上传快。
    • 任何对等方可能在任何时候仅具有块的子集就离开洪流,后续又重新加入洪流
    • 追踪器:每个洪流有一个基础设施节点,称为追踪器。
      • 当一个对等方加入洪流,向追踪器注册自己,并周期性告知它是否还在洪流中
      • 追踪器用于追踪参与洪流中的对等方

    运行机制:

    • 一个新的对等方Alice加入洪流,追踪器随机从对等方集合中选择一个集合,将该集合IP地址发给Alice。Alice与这些对等方尝试创建TCP连接,成功创建连接的对等方称为"邻近对等方"。
      • 这些邻近对等方是随时间波动的,会有其中的对等方离开,其他对等方又会尝试与Alice建立连接
    • Alice周期地询问邻近对等方所具有的块列表,基于块列表,Alice对自己没有的块发出请求,同时对请求块的邻居发送块
      • 应该从邻居请求哪些块呢? 这个由最稀缺优先技术决定,即针对自己没有的块在邻居中决定最稀缺的块并优先请求
      • 应该向哪些请求块的邻居发送块? BitTorrent提供了一种对换算法,先确定当前能够以最高速率向自己提供数据的4个邻居,这四个对等方称为疏通,并每过10秒重新确定。同时每过30秒,还要随机选择另外一个邻居。Alice向这5个对等方(前4个对等方和1个试探的对等方)发送块。而其他的邻近对等方均会被"阻塞"

    六、视频流和内容分发网

    1. 因特网视频

    视频是一系列的图像,以一种恒定的速率(如每秒24或30张图像来展示)来展现。

    视频一个重要的特征是能够被压缩,因此可以用**比特率(bit/s)**来衡量视频质量,比特率越高,图像质量越好,视觉感受越好。

    对于流式视频最重要的性能度量是端到端吞吐量,为了连续不断地布局,网络必须为流式应用提供平均吞吐量,这个流式应用至少与压缩视频的比特利率一样大。

    2. HTTP流和DASH

    HTTP流

    • 视频被存储在HTTP服务器中作为一个文件,每个文件有一个URL,用户与服务器创建TCP连接发送对该URL的HTTP GET请求
    • 服务器在HTTP响应报文中发送该文件,在用户侧,字节被收集在客户应用缓存中,一旦缓存中的字节数超过预先设定的门限,客户应用程序开始播放
    • HTTP流存在很严重的缺陷:
      • 不同客户或者对相同客户的不同时间段,客户可用的带宽都是不一样的,而HTTP流只能让所有客户接受到相同编码的视频

    DASH

    • 全称为经HTTP的动态适应性流(Dynamic Adaptive Streaming HTTP, DASH)
    • 视频被编码为不同的版本,每个版本具有不同比特率。用户可用带宽较高时,选择来自高速率版本的块;反之选择低速率的块
    • 每个视频版本存储在HTTP服务器中,每个版本都有一个URL,每个版本的URL和比特率由告示文件记录
    • 用户首先请求告示文件的各个版本,在下载块的同时测量接受带宽并允许一个速率决定算法来选择下次请求的块。

    3. 内容分发网

    对于一个因特网视频公司,提供流式视频最直接的方法是建立一个单一的大规模数据中心,在数据中心中存储所有视频。但这样做有以下问题

    • 客户远离数据中心的话,需要跨越很多通信链路,会带来停滞时延
    • 流视频会经相同的通信链路发送很多次,产生重复费用支出
    • 单点故障导致整个服务不用

    当今主流的视频流公司都利用了内容分发网(Content Distribution Network, CDN),CDN管理多个地理位置上的服务器,并在这些服务器中存储视频副本,同时试图将每个用户请求定向到一个能提供最好用户体验的CDN位置

    • 专用CDN由内容提供商自己所拥有
    • 第三方CDN代表多个内容提供商分发内容

    CDN服务器的部署原则有两种:

    • 深入:通过在遍及全球的接入网ISP中部署服务器集群来深入到ISP的接入网中,目标是接近端用户,减少端用户与CDN集群之间的链路和路由器数量
    • 邀请做客:通过在少量关键位置建造大集群来邀请到ISP做客,这些CDN集群通常放置在因特网交换点(IXP)处。

    并不是每个视频都会存在每个CDN集群中,CDN采用一种拉策略:如果客户像一个未存储请求视频的集群发送请求时,该集群检索该视频(从中心仓库或者另一个集群),向客户传输视频的同时在本地存储副本。

    3.1. CDN的拦截、重定向和集群选择

    用户主机浏览器检索一个特定视频(由URL标识)时,CDN必须拦截请求,从而可以:

    • 确定适合用于该客户的CDN服务器集群
    • 将客户的请求重定向到某台服务器

    CDN实现的请求的拦截以及重定向的方法是DNS

    3.2. CDN的集群选择策略

    所谓集群选择策略,即动态地将客户定向到CDN中某个服务器集群或数据中心的机制。

    常见的策略有:

    • 指派客户到地理上最邻近的集群,但是存在以下问题:
      • 就网络的长度或跳数而言,地理最近的集群可能并不是最近的集群
      • 某些端用户配置的是远地的LDNS(本地DNS)
      • 忽略了时延和可用带宽随因特网路径时间的变化,总是为特定用户指派相同的集群
    • 对集群和客户之间的路径和丢包性能执行周期性的实时测量,基于流量条件选择最好的集群
      • 缺点是许多LDNS被配置为不响应这种探测

    4. 热门视频流公司

    4.1. Netflix

    Netflix视频分发具有两个主要部件:亚马逊云和自己专有的CDN基础设施

    Netflix有一个完全运行在亚马逊云中的亚马逊服务器上的Web网站,同时亚马逊云还有以下关键功能:

    • 内容摄取:Netflix在能够向它的用户分发视频之前,必须首先获取视频并上载到亚马逊云的主机上并做内容处理
    • 内容处理:为每个视频生成不同格式,以适应不同端上运行的播放器。同时为每种格式和比特率生成一种不同版本,以便使用DASH流
    • 向CDN上载版本:视频处理完后向CDN上载这些版本

    Netflix有自己专用的的CDN,分别在IXP和它们自己的住宅ISP中安装了服务器机架。

    Netflix不需要DNS来做重定向,而是依靠Netflix软件(运行在亚马逊云中)直接告诉客户使用一台特定的CDN服务器。

    Netflix CDN使用推高速缓存而不是拉高速缓存,在非高峰时间段的预定时间将内容推入服务器。

    4.2. Youtube

    类似于Netflix,使用谷歌专用的CDN来分发视频。同时使用拉高速缓存和DNS重定向技术。

    Youtube使用的是HTT流,而不是DASH流,要求用户人工选择一个版本。

    4.3 看看

    使用的是P2P交付而不是客户-服务器交付。当对等方请求一个视频时,联系跟踪器,一发现具有该视频副本的其他对等方,之后并行地从这些对等方请求该视频的快。

    目前已经向混合CDN-P2P流逝系统迁移。大多数时候,客户请求来自CDN服务器的内容的开头部分,并且并行地从对等方请求内容。当P2P总流量满足视频播放,客户将从CDN停止流并只从对等方获得流。而当P2P流的流不够,则重新启动CDN连接。

    七、套接字编程

    前面提到过,网络应用程序有一对客户程序和服务器程序组成,它们运行在不同的端系统中。运行这两个程序时,创建了一个客户进程和服务器进程,两个进程之间通过从套接字读取和写入数据进行通信。

    典型的网络应用成有两大类:

    • 由标准协议(如一个RFC或某种其他标准文档)中所定义的操作的实现
      • 当开发者编写的客户端程序代码和服务器程序代码都遵从同一个RFC规格,这两个程序能够直接交互
    • 专用的网络应用程序
      • 客户和服务器程序应用的应用层协议没有公开发布在某RFC中或其他地方,开发者用代码完全控制应用的功能,而其他开发者不能开发出与该应用程序交互的代码

    现在我们自己来实现一个专用的客户-服务器网络应用程序,并分别以运行在TCP和UDP上来实现该应用程序。该应用程序的功能很简单:

    • 客户从键盘上读取一行字符并向服务器发送
    • 服务器接收数据并将字符转换为大写
    • 服务器将修改后的数据发送给客户
    • 客户接收数据并在监视器上显示

    这里采用Pyhton3来实现该程序。

    UDP套接字编程

    首先,需要说明的是,对于发送进程而言,需要为分组附上目的地地址(目的地主机IP和目的地套接字的端口号组成),同时发送方的源地址(源主机的IP地址和源套接字的端口组成)也要附在分组上,但这一步并不需要UDP程序代码实现,而是由底层操作系统实现。

    现在具体看代码,我们称客户程序为UDPClient.py,称服务器程序为UDPServer.py。

    以下是UDPClient.py的代码:

    # 导入socket模块
    from socket import *
    # 这里的hostname可以是具体的IP地址,也可以是服务器的主机名
    serverName = 'hostname'
    # 选择12000作为服务器程序套接字的端口号
    serPort = 12000
    # 创建客户套接字,AF_INET指示底层网络使用IPv4,SOCK_DGRAM意味着是一个UDP套接字
    # 这里没有指示客户端套接字的端口,这个由操作系统实现
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    # 用户输入字符串
    message = raw_input('Input lowercase sentence:')
    # 将字符串转为字节,并指定目的地地址向进程的套接字clientSocket发送分组
    clientSocket.sendto(message.encode(), (serverName, serverPort))
    # 接受服务器的数据,当分组到达客户时,分组数据被放置在变量modifiedMessage中,其源地址被放置到serverAddress
    modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
    # 将字节转为字符后打印
    print(modifiedMessage.decode())
    # 关闭套接字,关闭进程
    clientSocket.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    以下是UDPServer.py的代码:

    from socket import *
    serverPort = 12000
    serverSocket = socket(AF_INET, SOCK_DGRAM)
    # 将12000端口号与服务器的套接字绑定
    serverSocket.bind('', serverPort)
    print('The server is ready to receive')
    # 无限期接收并处理来自客户的分组
    while(true)
    	# 当分组到达时,分组数据被放置在变量message中,其源地址被放置到clientAddress
    	message, clientAddress = serverSocket.recvfrom(2048)
    	# 字符串转换
    	modifiedMessage = message.decode().upper()
    	# 将子符串转为字节,并指定目的地地址向进程的套接字serverSocket发送分组
    	serverSocket.sendto(modifiedMessage.encode(), clientAddress)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    TCP套接字编程

    首先说明TCP编程与UDP编程的区别:

    • 客户和服务器相互传输数据前,需要先建立一个TCP连接,创建该连接时将其与客户端套接字地址和服务器套接字地址关联。之后只需要经过套接字将数据丢进TCP连接,不需要像UDP一样为其附上目的地地址
    • TCP编程中,服务器有两个套接字
      • 欢迎套接字:所有要与服务器通信的客户的起始接触点
      • 连接套接字:为每个客户通信而生成的套接字
        TCPServer进程有两个套接字

    现在具体看代码,我们称客户程序为TCPClient.py,称服务器程序为TCPServer.py。

    以下是TCPClient.py的代码:

    # 导入socket模块
    from socket import *
    # 这里的hostname可以是具体的IP地址,也可以是服务器的主机名
    serverName = 'hostname'
    # 选择12000作为服务器程序套接字的端口号
    serPort = 12000
    # 创建客户套接字,AF_INET指示底层网络使用IPv4,SOCK_DGRAM意味着是一个UDP套接字
    # 这里没有指示客户端套接字的端口,这个由操作系统实现
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    # 创建TCP连接
    clientSocket.connect(serverName, serverPort)
    # 用户输入字符串
    message = raw_input('Input lowercase sentence:')
    # 将字符串转为字节,并向进程的套接字clientSocket发送分组,不再需要指定目的地地址
    clientSocket.sendto(message.encode())
    # 接受服务器的数据,当分组到达客户时,分组数据被放置在变量modifiedMessage中
    modifiedMessage = clientSocket.recv(1024)
    # 将字节转为字符后打印
    print(modifiedMessage.decode())
    # 关闭套接字,关闭进程
    clientSocket.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    以下是TCPServer.py的代码:

    from socket import *
    serverPort = 12000
    # 这里的serverSocket是欢迎套接字
    serverSocket = socket(AF_INET, SOCK_DGRAM)
    # 将12000端口号与服务器的套接字绑定
    serverSocket.bind('', serverPort)
    # 监听客户端TCP连接,定义请求连接的最大数
    serverSocket.listen(1);
    print('The server is ready to receive')
    # 无限期接收并处理来自客户的分组
    while(true)
    	# 创建一个连接套接字,由特定客户专用
    	connectionSocket, addr = serverSocket.accept()
    	sentence = serverSocket.recv(1024).decode().upper();
    	connectionSocket.send(sentence.encode())
    	# 关闭连接套接字
    	connectionSocket.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    【MATLAB教程案例43】初识matlab中三维数据处理相关函数——plot3,surf,mesh,isosurface,slice等
    【Redis 开发】缓存穿透解决
    优化开发人员对 K8s 安全的影响
    harbor部署实录
    PyTorch Geometric Temporal 介绍 —— 数据结构和RGCN的概念
    一种通过nacos动态配置实现多租户的log4j2日志物理隔离的设计
    Haskell 组合运算符
    八大基于比较的排序算法及三大基于非比较的排序算法总结
    makefile目标规则
    手把手带你入门 API 开发
  • 原文地址:https://blog.csdn.net/weixin_41402069/article/details/127945757