【事先声明】
这是对于中科大的计算机网络的网课的学习笔记,感谢郑烇老师的无偿分享
书籍是《计算机网络(自顶向下方法 第6版)》
需要的可以私信我,无偿分享,课程简介下也有
课程连接
服务端必须要比客户端先运行
客户端
对于C/S的中心模式,P2P去中心化,每个节点即可以请求别的节点的数据资源,也可以响应别的节点的数据与资源(为其它节点提供服务)
缺点是不好管理,资源也没办法集中。
对于前面两种模式的中和
有一台中心服务器(简单模型),然后有很多用户,用户有一定规模。
每当用户上线时,就会向服务器报告,自己拥有的资源目录。服务器就可以知道自己的用户所有用的资源数量以及目录。
当一个用户想要下载一个资源时,会向服务器请求这个资源,然后服务器就可以在已经上线的用户资源目录表中进行查找,可以差找到多个用于拥有这个资源,就会发送命令,让这个几个拥有资源的用户向那个请求资源的用户IP发送自己拥有的资源。然后服务请对于资源的发送进行管理,保证数据的有序与完整性。
这样就相当于多台服务器在向一个用户发送资源,一台服务器发送一部分资源,然后中心服务器组织管理后,就可以变成一个完整的资源。这样肯定比一台服务器发送资源速度更快,还可以多次进行校验,确保数据的完整性。
当用户越多,拥有的资源就越多,中心服务器可以管理的资源就越多,用户下载资源的速度就更快,就会吸引更多的用户进来。
P2P的方式发送资源,C/S的模式管理资源
应用层的协议要在传输层可以确保进程与进程间的通信(不同机器)的基础上,才能进行操作。
P2P架构中,也是有客户端进程与服务端进程的区分
一个客户端进程发送请求,得让服务端进程知道 请求这个数据的客户端进程 的唯一标志,并且可以根据这个唯一标志进行寻址,不然数据都不知道发给谁。
应用层通过调用层间的SAP,通过使用指定的API来获得网络通信的服务。
定义应用层之间的协议,报文格式,指定动作,时序…
通过OS提供的系统API,以及下层提供的通信服务API,来实现这些配置
进程为了接收与发送报文,必须要有一个标识。
一个进程可以用这三个唯一标识
本质上,一对主机进程之间的通信可以由两个端节点构成:IP+协议port
层间接口需要获得的信息
总结一下:传输层提供服务需要从应用层获得的信息有:要发送的数据,谁发的,发给谁的
传输层会根据这些进行进行封装成本层协议的报文段。
如果每次都传输一个这样完整的数据,会很麻烦。
在要时序一段时间都会发送一定数据的情况下,想办法省去前面的数据,只发送SDU。
可以利用API,表示通信的双方或者单方,就像利用OS提供的API打开文件一样,打开一次就够了,不用每次使用都fopen一下。
TCP socket表示的是一个会话关系,两台主机之间的会话关系。
UDP服务:两个进程之间通信之前不用建立连接。
所以,只是用一个本地的变量/标示 代表本应用(源进程)的源IP与源端口,因为UDP的目标分布时进程是不确定的。
UDP socket:源IP、源端口
不过传输时,必须要知道目标IP与目标端口,虽然UDP socket并不维护目标IP与目标端口,但是应用层必须需要将目标IP与目标端口发给传输送层。
与TCP socket相比,UDP套接字建立好后,需要发送SDU与目标IP、目标端口。
而TCP套接字建立好后,只需要发送SDU即可,因为TCP是建立好两个进程之间的连接的。
进程可以通过socket这个门户,基于传输层提供的基础服务上,实现报文交换
对于实时性要求高,对可靠性要求不高的应用需要这样的服务。
TCP与UDP都不提供加密服务,对于数据都是明文传输的,如果对数据进行抓包甚至可以获得密码等关键信息。
不过可以在应用层中使用SSL,进行数据加密,然后由传输层协议将加密后的数据传输到指定进程,这样可以保证安全性。
网页中的图片之类的对象,并不一定是对象本身,而是对象的URL链接。
任何一个对象都可以被一个URL唯一表示。
通过这个URL,可以访问互联网中的任何一个对象。
超文本传输协议,Web的应用层协议
在客户端雨服务端建立TCP的连接后,客户端向服务端发送HTTP的请求,服务端将客户端请求的对象封装成HTTP的报文,然后发送回客户端。
然后客户端获得服务端发送的HTTP报文,如果其中由URL,客户端就会根据URL中的主机、端口号,再次发送HTTP报文,去获得指定服务端中的对应的资源,因为资源可能存放在别的服务器中。
HTTP是无状态的:服务器不需要维护关于客户的任何状态,HTTP协议并不记录关于客户端请求的各种数据,只要请求,就按照请求响应即可。
优点是非常简单,响应速度非常快,可以支持更多的客户端请求。
TCP连接建立后,客户端发送一次HTTP请求后,服务端根据请求发送HTTP回应,然后TCP就断掉连接,这种只能进行一次HTTP报文交换。
执行步骤
TCP建立连接->发送HTTP请求->获得HTTP请求->断开TCP连接
该TCP连接只能传输一个请求报文和一个响应报文,即这种一次非持久性连接只能实现传输一个对象。
如果客户端请求的是一个Web网页,网页中包含着一个HTML文件与10个图片资源的URL,则这种非持久性连接,需要进行11次,才能在客户端的网站上展示一个完整的网页。
不过,这里并没有说请求10个URL的HTTP报文时,是串行的还是并行的。
现代浏览器可以设置并行HTTP请求数,当设置为1时,就可以保证是串行请求,默认情况下,浏览请通同时进行5-10个HTTP请求是没问题的,并行请求比较快。
定义:一个短分组 从客户端到服务端,再从服务端返回客户端,这一去一回所花费的时间。
对于非持久性连接的时间计算
总的时间:2个RTT+一个文件传输时间
如果使用非持久性连接,则传输n个对象则需要2n*RTT
的时间,如果是n个用户,请求n个对象,则需要耗费2n^2*RTT
的时间与空间资源,因为想要进行TCP连接,则需要服务请为其开辟一定的空间作为缓存,这个空间资源的消耗是巨大的。
如果是对于一个用户请求n个对象,则可以不关闭TCP连接,一直保持连接,直到请求结束后或者超过一定的时间间隔没有请求,才断开TCP连接。这样对于时间的花费只有(n+1)*RTT
。对于空间资源的消耗,可以一直使用之前开辟的那块缓存空间。学习过OS的人都知道,向系统申请空间资源也是需要花费一定的时间的,如果是频繁的向系统申请资源,会严重拖慢系统的运行速度,这样才会出现内存池的设计(提前申请出一定空间资源,需要的时候直接使用,避免时间开销)。
HTTP报文只有请求报文和响应报文两种格式
不同版本的HTTP协议,有不同的命令
HEAD命令,向服务器请求HTML的头部,对象不返回,一般用于调试跟踪,爬虫似乎也这样用。
如果请求命令是POST,则首部行后面还会加一个实体体,表示要向服务器提交的对象
如果是搜索内容,那么实体主体中就是输入的要搜索的内容
POST
向服务器提交表单,表单的内容就会在实体主体中。
GET
在请求行,URL后面,以参数的形式进行提交
服务器产生并响应发送该报文的时间
服务器的类型是一台 Apache Web 服务器
对象创建或最后的修改时间
对于即可能存在本地客户,也可能存在网络服务器缓存中的对象非常重要(跟数据一致性有关)
被发送对象中的字节数
被发送对象的类型
HTTP协议是无状态的
cookie技术可以让站点去记录或跟踪用户,记录用户之前访问网站的信息。
当用户第一次访问某网站时,服务器后台会为其分配创建一个唯一标识码的cookie文件,并放入后台的数据库中。在客户端中,cookie会记录用户的访问行为。让再次访问这个网站时,请求报文中会带上cookie标识码的首部行,服务器提取后,就会去数据库中那大记录用户行为的cookie文件,然后为其提供相应的服务。
相当于是给服务器加了一层Cache,使用了代理服务器,不直接访问原始服务器。
代理服务器可以重定向浏览器的访问IP,将其指向代理服务器,而不是指向原始服务器。
可以减少网络链路中的流量强度,原始服务器的访问量,提高访问速度。
这个一般是针对各个地区设置若干台Web缓冲器,可以直接在高速局域网内访问命中,不用全部接入公用因特网,减少网络的负载。
可以将相当一部分请求,在高速局域网内完成,剩下的未命中的部分再去共用因特网中访问原始服务器。
使用Web缓存器,虽然可以解决服务器与链路流量即访问速度的问题,但是这是相当于对原始服务器数据的多次拷贝,当代理服务器中的数据被改动后,原始服务器中的数据是否同样更新。
这就和内存与Cache的问题一样,保证两处的数据一致性。
当用户请求代理服务器得到响应,然后过一段时间,用户再次访问到了代理服务器,代理服务器并不确定这个资源再原始服务器中是否被修改了,会向原始服务器发送一个If_Modified_Since 上次访问的时间
,让原始服务器判断自从上次时间后,资源是否被修改。
304 No-Modified
,没有被修改这样通过HTTP协议中的条件GET,可以实现数据一致性。
与HTTP协议类似,FTP协议也是需要在TCP连接上进行文件传输的。
与HTTP协议不同的是,FTP是需要建立两个并行的TCP连接。
HTTP是无状态的协议,是不需要记录访问信息的,而FTP需要记录,会在整个会话期间保留用户状态,会跟踪记录用户在数据库文件目录中的访问,得与控制连接绑定起来。
在整个会话过程中,TCP控制连接是始终存在的,而TCP数据连接,传输完一个文件后,就会断开连接。每次传输一次文件就会建立一次新的数据连接。
从客户端到服务端的命令,与从服务端到客户端的回答,都是以7比特的ASCII数据,在TCP连接上进行传输。
当用户A发送邮件给用户B时,A会通过代理去访问自己的邮箱,然后发送邮件,文件数据封装成一个报文,进入外出报文队列中,等待发送到目标的邮件服务器中。当发送到邮件服务器中,然后会进行一个报文队列,等待分发到目标邮箱中。
用于从发送方邮件服务器发送报文到接收方邮件服务器中。
这里有一个情况
SMTP并不会使用中间服务器进行传输,而是直接建立源服务器与目标服务器的TCP连接,即使两台服务器很远。
SMTP是一种持续性连接,一个TCP连接可以发送多个报文数据。
极其简单的邮件访问协议
将报文于文件夹管理起来,可以不用讲报文下载到本地,可以远程访问文件夹中的报文信息。
允许用户远程组织报文与文件夹
会记录报文与文件夹的状态,报文ID与目录名之间的映射。
基于Web浏览器访问邮箱,变成了C/S模式
域名解析系统
用于将便于人类记忆的网址解析成IP地址
将人类访问的字符串转换为二进制的网络地址。
分布式服务器数据库的访问,避免集中式的访问造成奔溃。
DNS协议运行在UDP上,这样不需要握手,减少服务器的处理时间与负载。使用53号端口。
主机设备有着个非常符合URL规范的命名,这个规范的主机名不好记忆,所以也存在便于记忆的别名,访问别名时,也期望的是访问这个主机。
当应用程序访问的是别名时,通过DNS的客户端可以获得规范主机名与对应的IP地址。
对于一个网址/IP地址 可以由横夺态不同地区不同地点,不同型号的服务器为其提供服务,DNS可以根据实际情况来决定,你想要访问的网址,到底由哪台服务器为你提供服务。
比如说,当人多的时候,就会给你分配远一点的服务器为你提供服务,人少的时候,就会决定让你家附近的缓存服务器为你提供服务…
DNS采用层次树状结构进行命名
域的划分是逻辑上,而不是物理上的。
同一个域名下的两台主机,可以在不同的网络、地区、甚至国家中。
也可能两台相邻的主机是分别属于两个顶级域名下的。
最简单的DNS模型是,只有唯一一台DNS服务器,所有的域名解析请求都需要访问这台服务器,会存在各种各样的问题。
部分层次结构,下面还有更庞大的细分DNS服务器
由一些公司维护,任何人都可以申请挂靠在这个顶级域下
主要是一些组织机构使用的,用于管理维护自己网络服务器。
从一台主机想要访问某个地址,则首先需要通过访问本地DNS,通过本地DNS服务器代理,去根服务器获取目标IP的顶级域服务器,然后拿到顶级域服务器的IP后,去请求顶级域服务器去查找,挂靠在顶级域下的某个网址,通过网址的欧胡追逐层解析,拿到顶级域下的权威域服务器的名字,向权威与服务器请求后,可以获得权威域服务器的IP,本地DNS服务器,在去权威域服务器请求查找后面的网址,就可以获得目标IP,然后把目标IP返回给请求主机
从请求的网址,从后往前,依次去查询 域的DNS服务器,直到查到权威服务器后,在权威服务器中查到想要的主机。
这个请求查询的过程中,一共有8次的报文请求,从根服务器一路访问到权威服务器。
这种是迭代查询的模式
递归查询的模式
两者需要的报文数都差不多,只不过负载较大的服务器不同,递归查询模式,根服务器的负载应该是最大的,基本上全世界的流量都得从根服务器这里过,且根服务器还得去发送请求,向下查询。
迭代模式将服务器的负载放到了本地DNS服务器上,由本地DNS来处理向下查询。
为了避免大量数据报文在因特网上流动,减少延时与DNS报文数。因为本地DNS服务器与其它层次服务器请求是要走因特网的。
DNS服务器会将获得的IP域名转换缓存在本地中,当再次需要访问时,就直接从本地回应,不用再次请求别的DNS服务器了
第一次对于跟根服务器的访问,得到的回应不就是那一些顶级域的服务器的IP吗?这样可以i直接存在缓存中,避免总数访问跟服务器,虽然子各个地球都有跟服务器的镜像,但是访问的数量太多了,还是会造成流量强度价太高,因为服务器的层次越高,访问的频率越高。
这样利用DNS服务器的缓存技术,可以绕开根服务器的请求(根服务器请求的频率太多了,就像Cache一眼给,可以直接命中DNS缓存,不用请求原服务器),可以绕开对顶级域服务器的请求…绕开一些访问频率高的域服务器。缓存技术可以加快访问速率,减少公用因特网中的报文数量。
DNS分布式服务器的数据库中,存储的是资源记录
资源记录提供了主机名-IP地址的映射,DNS的每条回答报文中,提供了一条或多条资源记录。
资源记录的模板类型(Name,Value,Type,TTL)
资源记录在缓存中生存的时间,决定了该资源记录什么时候可以被从缓存中删除。
如果很大,说明记录的时间很长,说明该资源记录是一个权威记录,要被使用的频率很高。
如果不大,说明是个缓存记录,到时间直接删掉(一般两天),有些服务器过一段时间IP会改动,为了数据一致性,防止下次找不到。
资源记录中的Name
与Value
都是由Type
决定的。
只有两种报文:查询报文和回答报文。查询报文和回答报文有着相同的格式。
使用案例:文件分发,流媒体,互联网语音
如果是以C/S的模式进行文件的分发,N个用户,每份文件F个比特。
对于服务器而言,服务器需要与每个用户建立逻辑连接,然后上载NF个比特进入因特网,上载速率为u,然后用户各自从因特网以一定的下载速率 d 从因特网下载。所以完成这个任务需要的最少的时间是, max F d m i n , N F u \max {\dfrac{F}{d_{min}},\dfrac{NF}{u}} maxdminF,uNF
用户可以并行的从因特网中下载,但是服务器分别给这些用户上层文件,逻辑上是一一建立的连接,所以是NF个比特的文件。
整个任务的关键部分,在于服务器文件上载到因特网中的耗时,随着申请的用户增加,耗时也是线性增加的。
采用P2P的模式的化,服务器只需要上载一份文件给一个用户,然后用户再上载文件到因特网中,给另外一个用户…然后拥有文件的用户给未拥有文件的用户上传文件,让他们下载…
把时间分散出去了,服务器上传文件的时间,用户下载文件的时间,所有用户上传文件到因特网上的时间(虽然是点对点传输,但是物理上还是得上传到因特网上,然后沿着路径发送到目标用户)
整个耗时, max F u , F d m i n , N F u + ∑ u i \max {\dfrac{F}{u},\dfrac{F}{d_{min}},\dfrac{NF}{u+\sum u_i}} maxuF,dminF,u+∑uiNF
当然,也可以多个用户给一个用户传送文件中的一部分,这样算是并行传输文件,耗时更短,这样的化,任务的耗时瓶颈就是用户的下载能力了。
有一个中心服务器,用于对于各节点所拥有的文件的目录进行索引查找,向下载某个文件时,需要先去中心服务器请求,然后中心服务器找到后,就会让另一个节点向这个节点建立连接,然后发送文件。
缺点就是,版权问题,单点故障(中心服务器挂了就无法使用了)
去中心化,没有中心服务器,每个节点之间都是对等的,是一个图形结构。
每个节点会与周围节点建立连接。
进行查询时,节点回向所有建立连接的节点进行查询,然后再向一级邻居节点进行周围的节点进行文件目录查询,一层层向下查询出去,直到找到想要的文件,然后反向返回回应报文,然后建立两个节点之间的连接,进行文件传输。变成了图的查找,BFS或者DFS。
问题是,这样需要耗费非常大的资源,万一那个文件大家都没有,就会无穷无尽的查找下去。可以通过一些限制条件,剪枝算法、限制算法进行限制性图搜索。如设置TTL,记录遍历过的节点…
每个节点要么属于一个小组中的组员,或者是小组的组长,然后小组与小组通过组长建立连接,组长会负责跟踪组员中的文件目录,小组想查找其它组的文件目录,需要小组组长之间建立连接。
组长是组中的中心服务器,组长与组长之间是对等的。
组内层面是集中式的,组间层面是完全式的。
这些资源都需要被一个哈希表维护起来,一个散列值作为文件的唯一的标示,然后还有文件内容与文件描述(文本)。
用户在检索文件时,实际上是在匹配文件描述(文本)。
请求时,是通过文件的哈希值进行对文件操作。
节点之间通过IP或者分配哈希值,建立有序的拓扑结构,如环状,树状…
对于一些占据主要带宽的流媒体应用,需要下载大量的数据,占用大量的下行带宽,比如视频应用
视频文件内容是在HTTP协议上传输。
客户端根据主机的实际情况,带宽阻塞程度,视频设置、剩余缓存区…诸多因素,选择最合适的视频块向服务器请求。
服务器如何通过网络向上百万用户同时流化视频内容
选择一个超大的,单个的超级服务器中心
容易出现单点故障,周边网络堵塞,资源浪费…该方法不可拓展
内容分发网络CDN
全网部署缓存节点、存储服务,就近为用户提供服务,加速访问。
ISP需要向CDN的运营商购买CDN服务器,然后将自己的一些服务、资源,缓存到CDN的服务器上,用户访问时,通过DNS域名解析,重定向到就近的CDN服务器上,加速网络服务,缓解流量压力。
这种CDN服务器就是Cache服务器,直接命中高速访问缓存服务器,就不用去原始服务器进行访问。
CDN服务商,将很多缓存服务器部署在网络边缘(设备)的接入网中,离用户非常近,可以提供非常优质的服务,但是需要大量的服务器来维护,成本很高
将CDN服务器部署在上层ISP的网络的关键节点处,然后通过线路,将服务器群连接起来。虽然离用户比较远,但是位于网络的关键节点处,还是可以提供较好的服务。
CDN主要是在协议栈的应用层,网络结构的网络边缘上进行网络加速的服务。
应用层进程通过访问Socket API来访问传输服务。
connect
,如果服务器不同意连接,客户端的执行流也会阻塞在这个连接中,直到服务端同意连接。connection socket
,该套接字会捆绑客户端IP与PORT和服务端IP与PORT,服务端可以通过这个socket与客户端进行通信。conection socket
就会被关掉,然后welcome socket
依然在服务端等待请求。应用进程,标示本地的端节点,所有的通信、操作都是通过对这个端节点进行操作。
该结构体对象,是用于调用域名解析时的参数,返回后,将该对象的IP地址拷贝到sockaddr_in
的IP
部分。
一个端口可以被多个任务/套接字使用,只要套接字不一样,从这个端口进行来报文就可以被分别识别。
在服务端与客户端之间没有连接,不需要握手。
发送端在每一个报文中都必须指明一个目标IP与端口。
发送的数据可能会乱序,也可能会丢失。
接收端需要从收到的报文中解析处发送端的IP与端口。