1.1 从访问网页开始
在探讨具体的技术原理之前,我们来搞清楚“网络通信”的定义:它是指媒体信息通过网络从一端传递到另外一端。媒体信息的内容主要是话音、文字、图片和视频图像。至于信息如何通过网络传递,例如:一个字符怎么变成电波信号,电波信号又如何在网络设备中传输和接收的。对于这些我们应用开发人员来说是不需要去深究的。而大家所要关心的是应用层面的东西,例如:通信双方是怎么联系起来的?通信的内容怎么表示才能使双方理解?当某一端出现故障以后,如何让另一端知道?
假设有一对热恋中的青年男女,GG约MM去看电影,下面是拨打电话的过程:
MM:喂
GG:喂(应答一下)
GG:亲爱的,今晚我们去看电影吧?
MM:好啊(应答一下)
。。。。。。
这里通话的两端是人在操作,人是有语言感知能力的,只要双方说的语言能使对方明白意思就行。如果通话的主体是电脑,则需要更严谨的定义,因为电脑并没有语言感知能力,它只能识别事先定义好的规则,这样才能理解对方的意思。例如:电脑在发出第一个“喂”的时候,要约定这个内容是什么类型(例如:通话准备),然后另一端再根据类型应答一下(例如:通话准备完毕)。所以通信的过程就是:请求-应答信息的往返过程。
很多人天天上网,可能从来没去琢磨上网的过程是怎么样的,因为这已成为生活的一部分,是想当然的事情。如果您能从技术角度分析上网的过程,就大致明白网络通信是怎么回事,而了解了通信原理以后,再去做网站、WEB应用开发就能很快上手了。接下来我们分析一般情况下的应用场景:
第1步:用户打开浏览器,并输入网址;
第2步:系统连接web服务器;
第3步:系统返回页面内容;
第4步:浏览器显示页面内容。
从使用者的层面来看,就是这简单的四步;假如用户给你提出了这样的需求,该怎么去进行下一步的技术架构分析呢?
【图1-1 请求网页过程】
与用户使用场景相比,中间多了几步域名解析的过程。如果直接输入的是IP,这几个步骤就会省略。在互联网上,通常是以域名符号作为地址;而网络上的每个节点是以IP地址标识的,所以域名符号与IP地址要有个转换映射过程。这就是“域名解析服务”,简称DNS。DNS是由国际互联网组织提供的一种基础功能服务,域名解析时会按照DNS的树状结构逐级往上找,直到找到匹配的结果为止。接下来我们主要分析一下“浏览器”与“Web服务器”的交互细节:
浏览器需要解析、呈现的内容是什么?把文字、图片、视频等按照HTML语法规则来组织的内容形式,简称HTML页面。浏览器要负责解释网页上的HTML语法,所以它就起到一个语法解释的作用,是一个网页脚本的解释引擎。但Web服务器是怎么把用户需要的HTML页面传递到客户端的呢?在传递的过程中,又是以什么形式表现的呢?这里就出现了一个HTTP协议,它负责对HTML页面内容封包,然后通信双方根据协议进行请求应答。HTTP协议只是整个网络协议族里面的一种应用协议。
【图1-2 TCP/IP协议栈】
逻辑上,发送的数据流会沿着这个栈自上向下传递,相反的接收数据流也会自下向上传递。在浏览器请求数据的时候,Web服务器首先读取指定位置的HTML文件,然后层层对数据流封包,加上头部或尾部【参见第三章的TCP/IP协议】,直到发送出去。接收方负责层层解包,到了应用层后,只包含HTTP协议头和网页内容的数据流了;然后浏览器根据协议头里面的类型来区分网页的内容、格式等属性【参考 HTTP协议的定义】。
客户端(浏览器)与Web服务器交互的时候,传递的是基于HTTP协议的HTML数据包。每打开一个页面,都是一次新的请求,也就是每次请求都是独立的,不同的请求没有上下文环境【Context】数据。如果某个应用系统需要把关键的数据【例如:用户名,订单号】在每次请求的时候都把它们传递到服务器端,以此进行某些操作的话。这个时候通常有两种做法:
1:存储在客户端(如:COOKIE技术);
2:存储在服务器端(SESSION, APPLICATION技术)。
假如选择在客户端存储,那么每次需要把数据放在HTTP协议的COOKIE属性,然后服务器端负责解析接收该属性值。如果存储在服务器端,就不需要每次传递这些数据,Web服务器要使用时直接从内存或其它存储系统读取。这两种方法区别如下:
方法 |
信息量大小 |
保持时间 |
应用范围 |
保存位置 |
APPLICATION |
任意大小 |
这个应用程序的生命周期 |
所要用户 |
服务器端 |
SESSION |
小量,简单的数据 |
用户活动时间 + 一段延迟时间(一般为 30分钟) |
单个用户 |
服务器端 |
COOKIE |
小量,简单的数据 |
|
单个用户 |
客户端 |
1.2 客户端—服务器编程模型
每个网络应用都是基于客户端—服务器模型的。根据这个模型,一个应用是由一个服务器进程和一个或多个客户端进程组成。服务器管理某种资源,并且通过操作这种资源来为它的客户端提供某种服务。例如,一个Web服务器管理了一组磁盘文件,它会在接收到客户端的请求后,进行检索和执行。FTP服务器就管理了一组磁盘文件,它会为客户端进行存储和检索。
客户端—服务器模型中的基本模型是事务,这个事务由四步组成:
<!--[if !supportLists]-->1、 <!--[endif]-->当一个客户端需要服务时,它向服务器发送一个请求。例如,当Web浏览器打开一个网页时,它就发送一个请求给Web服务器。
<!--[if !supportLists]-->2、 <!--[endif]-->服务器收到请求后,解释请求命令,并以适当的方式操作它的资源。例如,当Web服务器接收到浏览器发出的请求后,它读一个磁盘文件。
<!--[if !supportLists]-->3、 <!--[endif]-->服务器给客户端发送一个响应,并等待下一个请求。例如,Web服务器将文件内容发送给客户端。
<!--[if !supportLists]-->4、 <!--[endif]-->客户端收到响应并处理它。例如,当Web浏览器收到来自服务器的一个页面后,它就在屏幕上显示此页。
这里的客户端和服务器是逻辑上的概念,并不是物理机器,在操作系统里面表现的就是一个应用进程,它们可以同时运行在同一台主机或是不同的主机上。无论客户端和服务器是怎样映射到主机上的,客户端—服务器模型是相同的。
1.3 网络上数据的传送过程
互联网络的重要特征就是,它能由采用完全不同或不兼容技术的各种局域网和广域网组成。每台主机和其它每台主机都是物理相连的,但是如何使得某台源主机跨过所有这些不兼容的网络发送数据到另一台目的主机成为可能呢?
解决办法是有一个运行在每台主机和路由器上的协议软件,它消除了不同网络之间的差异。这个软件负责解释执行一种协议,控制主机和路由器协同工作来实现数据传输。这种协议必须提供两种基本能力:
1)命名方法。不同的局域网技术有不同和不兼容的方式来为主机分配地址。互联网络协议通过定义一种一致的主机地址格式,消除了这些差异。每台主机会被分配至少一个这种网络地址,这个地址唯一地标识了它。
<!--[if !supportLists]--><!--[endif]-->2)传输机制。在电缆上的编码位和将这些位封装成帧方面,不同的网络互联技术有不同的和不兼容的方式。互联网络协议通过定义一种把数据位捆扎成不连续的组块 ——也就是包,从而消除了这些差异。一个包是由包和包体组成的,其中包头包括整个包的大小以及源主机和目的主机的地址,包体就是源主机发出的数据。
下图展示了一个主机和路由器如何使用互联网络协议在不兼容的局域网间传输数送的示例。
PH: 互联网络包头; FH1: LAN1的帧头;FH2:LAN2 的帧头。
这个互联网络示例由两个局域网通过一台路由器连接而成。一个客户端运行在主机A上,主机A与LAN1相连,它发送了一串数据字节到运行在主机B上的服务器端,主机B则连接在LAN2上。这个过程有8个基本步骤:
<!--[if !supportLists]-->1、 <!--[endif]-->运行在主机A上的客户端进行了一个系统调用,从客户端的虚拟地址空间复制数据到内核缓冲区。
<!--[if !supportLists]-->2、 <!--[endif]-->主机A上的协议软件通过在数据前附加互联网络的包头和LAN1帧头,创建了一个LAN1帧。根据互联网络的包头寻址到主机B。LAN1帧头寻址到路由器。然后它传输此帧到适配器。注意,LAN1帧的有效载荷是一个互联网络包,该包的有效载荷是实际的用户数据。这种封装是基本的网络互联方法之一。
<!--[if !supportLists]-->3、 <!--[endif]-->LAN1适配器复制该帧到网络上。
<!--[if !supportLists]-->4、 <!--[endif]-->当此帧到达路由器时,路由器的LAN1适配器从电缆上读取它,并把它传送到协议软件。
<!--[if !supportLists]-->5、 <!--[endif]-->路由器从互联网络包头中提取目的地址,并用它作为路由表的索引,确定向哪里转发这个包,在本例中是LAN2。路由器剥落旧的LAN1的帧头,加上寻址到主机B的新的LAN2帧头,并把得到的帧传送到适配器。
<!--[if !supportLists]-->6、 <!--[endif]-->路由器的LAN2适配器复制该帧到网络上。
<!--[if !supportLists]-->7、 <!--[endif]-->当此帧到达主机B时,它的适配器从电缆上读到此帧,并将它传送到协议软件中。
<!--[if !supportLists]-->8、 <!--[endif]-->最后,主机B上的协议软件剥落包头和帧头。当服务器进行一个读取这些数据的系统调用时,协议软件最终将得到数据复制到服务器的虚拟地址空间。
当然,这里我们掩盖了许多复杂的问题。如果不同的网络有不同的帧大小的最大值,该怎么办呢?路由器如何知道往哪里转发帧呢?当网络拓扑变化时,如何通知路由器?如果一个包丢失了又会如何呢?虽然如此,我们的示例抓住了互联网络的精髓,封装是关键。

