Q. 暂存疑问

  1. p74,代理服务器减少客户请求响应时间的问题;

    2. 应用层

    2.1 应用层协议原理

    什么是应用程序体系结构?
    与网络体系结构不同,应用程序体系结构由应用程序开发者设计,规定如何在各个终端上组织应用程序。主要的体系结构有:P2P、CS

不同终端之间是通过什么通信的?
通信发生在不同终端的不同进程之间。在一对进程通信的场景中,发起通信的被称为“客户”,在会话开始时等待消息的称为“服务器”(即使在P2P体系中)。

进程如何通过网络发送和接收消息?
进程通过套接字(socket)的软件接口向网络发送和接收报文。socket相当于应用程序和网络之间的API,开发者可以控制socket在应用层端的一切属性,但是对socket在运输层却几乎没有控制权。
image.png
如何找到进程的地址?
IP Address + Port Number

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

  1. 可靠的数据传输

有的程序需要可靠传输,金融交易等,有的程序丢失少量数据影响不大,如视频软件等。

  1. 特定速率的吞吐量

某些应用程序需要运输层能提供一定速率以上的吞吐量,比如语音通话程序对语音以32kbps的速率编码,则运输层需要提供至少和这个速率相当的吞吐量;
具有吞吐量需求的程序称为:带宽敏感型应用(bandwidth sensitive application);
没有特定吞吐量需求的程序称为:弹性应用(elastic application);

  1. 定时

某些应用程序需要发送方注入socket的比特到达接收方socket的时间不高于特定数字,例如即时网络游戏等。

  1. 安全性

    2.1.5 应用层协议的作用

    应用程序与网络交互方式是将报文通过socket,而如何构造这些报文、报文每个字段的含义以及进程何时发送报文则由应用层协议所规定。

    2.2 Web和HTTP

    web为什么能够成功?
    主动按需提供服务,想获取什么内容就能够主动找到内容,而不同于广播和电视的被动接收。

    2.2.1 HTTP总览

    HTTP:HyperText Transfer Protocol

HTTP是web的应用层协议,HTTP由两个程序实现:客户程序 + 服务器程序

什么是web page(web页面)?
web page由对象组成,一般包括一个基本的HTML文件对象和其他例如JPG图像、Java小程序、视频片段这样的对象。

什么是URL?
Uniform Resource Locator(唯一资源定位器)
URL是web对象的地址,通常由:“存放对象的服务器主机名 + 路径”构成。
例如, URL 地址 http://www. someSchoo1. edu/someDepartment/picture.gif, 其中的 www.someSchoo1.edu 就是主机名, /someDepartment/picture.gif 创就是路径名。

什么是无状态协议?
客户在短时间内重复向服务器请求同一个对象多次,服务器就响应多次,不会因为响应过了就不响应了,因为HTTP是一个无状态协议,所以不存储客户的状态信息。

2.2.2 非持续连接和持续连接

TCP为HTTP提供可靠连接服务,如果每个HTTP请求+响应都建立一次TCP连接,那么就称为非持续连接(non-persistent Connection);如果所有的响应和请求都通过同一个TCP连接,则称为持续连接。

客户访问服务器中一个具有11个对象的页面的过程是怎么样的?

  1. 首先通过“三次握手”建立TCP连接:客户向服务器发送一个小TCP报文段,服务器回应一个小的TCP报文段,最后客户再向服务器返回确认;
  2. 服务器在收到客户的返回确认后,服务器就在该TCP连接上发送HTML文件;

在非持续连接中,要建立大量TCP连接,如何提高访问对象的速度?
用户能够配置浏览器来控制连接的并行度。在默认方式下,大部分浏览器打开 5 -10 个并行的 TCP 连接,而每条连接处理一个请求响应事务。

web访问总的响应时间如何计算?
RTT:Round-Trip Time(往返时间)
总响应时间为2个RTT加上HTML文件的传输时间:(确认报文和访问请求同时发送)
image.png

2.2.3 HTTP报文格式

  1. HTTP请求报文

一个典型的请求报文例子:
image.png

  • Connection:close指是使用非持续连接;
  • User-agent:用户的代理,即浏览器类型,这里浏览器类型是 Mozilla/5. 0, 即 Firefox 浏览器;
  • Accept-language : 首部行,表示用户想得到该对象的法语版本 (如果服务器中有这样的对象的话) ; 否则,服务器应当发送它的默认版本;

    1. <br />每行对应的信息:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21430542/1625574447490-3e98930d-5bda-4cda-8e2d-afeae6992864.png#crop=0&crop=0&crop=1&crop=1&height=310&id=ypvEe&margin=%5Bobject%20Object%5D&name=image.png&originHeight=620&originWidth=926&originalType=binary&ratio=1&rotation=0&showTitle=false&size=498987&status=done&style=none&title=&width=463)<br />使用GET方法时,实体体为空;使用POST方法时才使用实体体,例如填写web表单向服务器传递消息。<br />注意:填写web表单也可不使用POST方法,可使用GET方法将表单信息放在URL中。
  1. HTTP响应报文

image.png

  • Last-Modified:服务器上次更新的时间;
  • Content-Length: 实体体的字节数;
  • Content-Type : 实体体中的对象是HTML文本;

    1. <br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21430542/1625574919488-5432c475-a4ba-4162-9193-212c3682f331.png#crop=0&crop=0&crop=1&crop=1&height=305&id=xLoH5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=610&originWidth=944&originalType=binary&ratio=1&rotation=0&showTitle=false&size=536765&status=done&style=none&title=&width=472)<br />常见状态码:<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21430542/1625575078640-14a60c15-c2f8-4dca-a819-fb7e838220d4.png#crop=0&crop=0&crop=1&crop=1&height=163&id=Ys2s4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=362&originWidth=1622&originalType=binary&ratio=1&rotation=0&showTitle=false&size=476032&status=done&style=none&title=&width=731)
  • 304 Not Modified:请求的内容是从代理服务器获取的,并且与远程服务器数据一致,无需修改

更多状态码:菜鸟教程

2.2.4 cookie

cookie的作用是使web站点能够区分不同的客户,以限制用户的访问或者将内容与用户的身份相关联。

cookie有四个组件:

  1. HTTP响应报文中的一个首部行;
  2. HTTP请求报文中的一个首部行;
  3. 用户终端的一个cookie文件;
  4. web站点后端数据库的一个表项;

假设Bob使用首次访问Amazon,之前访问过ebay:
image.png

2.2.5 web缓存器

web缓存器(web cache),也称为代理服务器(proxy server),功能相当于存储系统中的cache。
image.png
代理服务器的作用:

  1. 大量减少客户请求的响应时间,客户与代理间的带宽往往大于客户与初始服务器之间的带宽;
  2. 大量减少配置了代理服务器的机构的接入链路到Internet的通信量;

    2.2.6 条件get方法

    代理服务器中缓存的对象副本过时(在初始服务器端已更新),需要对代理服务器中的对象进行更新。
    更新的方法为,每一段时间代理服务器向初始服务器发送一个条件GET请求,如下:
    image.png
    If-modified-sicne是原先响应报文中的Date
    如果没有修改,则返回如下:该response没有实体数据,提示客户调用自身缓存加载页面。
    image.png

    2.4 DNS

    Domain Name System 域名系统
    功能:负责主机名(hostname)和IP地址之间的转换

DNS的工作过程是怎么样的?

  1. 用户主机的应用程序调用DNS客户端,指明要转换的主机名;
  2. DNS客户端使用UDP数据报经过端口53向网络发送一个DNS查询报文;
  3. DNS客户端收到对应的DNS回答报文;
  4. DNS客户端将应答结果传递给调用DNS的应用程序;

为什么说DNS服务器是一个分布式数据库?
有三种层次的DNS服务器:

  1. 根DNS服务器:提供TLD服务器的IP地址;
  2. 顶级域(Top-leval Domain,TLD)DNS服务器:提供权威DNS服务器的地址;
  3. 权威DNS服务器:提供主机的IP地址;

image.png

什么是本地DNS服务器?
本地DNS服务器不属于DNS服务器的层次结构,每个ISP都有一台本地的DNS服务器。当主机与某个ISP连接时,该ISP分配给主机一个IP地址,主机则拥有一台或多台本地DNS服务器的IP地址。

通过一个例子理解本地DNS服务器的工作方式:
假设主机cse. nyu. edu 想知道主机 gaia.cs.umass.edu的IP地址。

  1. 请求主机向dns.nyu.cn发送一个含有gaia.cs.umass.edu的DNS查询报文;
  2. 本地DNS服务器向根服务器转发该报文;
  3. 根服务器根据edu前缀返回TLD服务器的IP地址;
  4. 本地DNS服务器向TLD服务器转发查询报文;
  5. TLD服务器根据umass.edu前缀返回权威DNS服务器的IP地址;
  6. 本地DNS服务器向权威DNS服务器转发请求报文;
  7. 权威DNS服务器返回gaia.cs.umass.edu的IP地址;
  8. 本地DNS服务器向请求主机返回gaia.cs.umass.edu的IP地址;

image.png

什么是递归查询(recursive query)和迭代查询(iterative query)?

  • 上图中请求主机的1、8步骤就是递归查询
  • 本地DNS服务器与其他DNS服务器之间的查询则为迭代查询

DNS缓存:如果在DNS服务器中缓存了一台主机名/IP 地址,则对另一个对相同DNS查询到达该DNS 服务器时,该 DNS 服务器就能够提供所要求的 IP 地址,即使它不是该主机名的权威服务器。由于主机名与 IP 地址间的映射并不是永久的, DNS 服务器在一段时间后(通常设置为两天)将丢弃缓存的信息。

2.4.3 DNS记录和报文

略过

2.5 P2P文件分发

略过

2.6 视频流和CDN

2.6.2 HTTP和DASH

什么是DASH?
Dynamic Adaptive Streaming over HTTP(经HTTP的动态适应流)
使用HTTP实现视频流的最大缺陷是客户只能收到相同大小编码的视频。而在DASH中,视频编码为几个不同的版本,其中每个版本具有不同的比特率,对应于不 同的质量水平。

2.6.3 CDN

Content Distribution Network 内容分发网

为什么不使用单一的数据中心提供流式视频服务?

  1. 如果客户距离过远,将跨越多个链路,如果瓶颈链路吞吐量过小则容易产生延迟;
  2. 视频流在单个链路可能重复传送多次;
  3. 单个数据中心的单点故障问题;

CDN的工作原理是什么?
CDN管理分布在多个地理位置的CDN服务器,并在其中存储(视频)副本,并且让每个用户请求定向到能提供最好服务的特定CDN服务器位置。

CDN的两种服务器安装原则是?

  1. 尽可能多的部署服务器,CDN服务器尽可能的靠近用户,缺点是维护和管理众多的服务器集群困难;
  2. 在少量关键位置部署CDN服务器,缺点是对距离远的用户吞吐量低;

什么是专用CDN和第三方CDN?
专用CDN:一般巨头使用,专门为一个内容提供商部署的CDN,如Google;
第三方CDN:多个内容提供商共同使用;

如何定向到特定的CDN服务器?
使用DNS服务器来定向CDN服务器。

例如客户想要访问video.netcinema.com(该网站使用KingCDN的第三方CDN)的视频时:

  1. 用户访问位于NetCinema的网页;
  2. 用户点击视频链接时,用户主机发送了一个对video.netcinema.com的DNS请求;
  3. 本地DNS经一系列中继操作后转发给NetCinema的权威DNS服务器;
  4. 为了使用第三方CDN,NetCinema的权威DNS服务器返回一个KingCDN的权威服务器IP;
  5. 本地DNS向该IP发送DNS请求,该CDN权威服务器返回一个特定的CDN服务器的IP地址;
  6. 客户向该CDN服务器地址建立TCP连接,并且发出对该视频的 HTTP GET 请求,如果使用了 DASH, 服务器将首先向客户发送具有 URL 列表的告示文件,每个 URL 对应视频的每个版本,并且客户将动态地选择来自不同版本的块;

    1. <br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21430542/1625658349837-36de4cac-0d05-469f-a5fb-16c62b7e2371.png#crop=0&crop=0&crop=1&crop=1&height=355&id=hR3AM&margin=%5Bobject%20Object%5D&name=image.png&originHeight=710&originWidth=894&originalType=binary&ratio=1&rotation=0&showTitle=false&size=299292&status=done&style=none&title=&width=447)

    2.6.4 CDN案例

    略过

    2.7 socket编程

    image.png
    使用如下例子来演示UDP和TCP的socket编程:

  7. 用户在键盘输入一行字符并发送给服务器;

  8. 服务器接收该字符串并转为大写;
  9. 服务器将修改后的字符串返回给客户;
  10. 客户接收数据并在屏幕上打印出来;

2.7.1 UDP socket编程

image.png
客户端:

  1. from socket import *
  2. serverName = 'hostname'
  3. serverPort = 12000
  4. # 创建client端socket,第一个参数表示IPv4,第二个参数表示UDP类型socket
  5. clientSocket = socket(AF_INET, SOCK_DGRAM)
  6. message = input('Input lowercase sentence:')
  7. # 向socket发送字节,并指明目的地之
  8. clientSocket.sendto(message.encode(), (serverName, serverPort))
  9. # 接收修改后的字符串和服务器地址,取缓存2048作为输入
  10. modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
  11. # 输出修改后的字符串
  12. print(modifiedMessage.decode())
  13. # 关闭套接字
  14. clientSocket.close()

服务端:

  1. from socket import *
  2. serverPort = 12000
  3. serverSocket = socket(AF_INET, SOCK_DGRAM)
  4. # 将端口号12000与服务端socket绑定,向该服务器IP的12000端口发送的分组将导向该套接字
  5. serverSocket.bind(('', serverPort))
  6. print("The server is ready to receive")
  7. while True:
  8. message, clientAddress = serverSocket.recvfrom(2048)
  9. modifiedMessage = message.decode().upper()
  10. serverSocket.sendto(modifiedMessage.encode(), clientAddress)

2.7.2 TCP socket编程

为什么基于TCP的进程交互在服务器端需要欢迎套接字连接套接字
因为在客户和服务器产生数据交互之前,需要先建立TCP连接,服务器创建一个欢迎套接字来处理所有的TCP连接请求,一旦连接建立,服务器将创建一个专门的连接套接字来与专门的客户交互数据。
image.png
image.png
TCPClient:

  1. from socket import *
  2. serverName = 'servername'
  3. serverPort = 12000
  4. clientSocket = socket(AF_INET, SOCK_STREAM)
  5. # 向服务器发起TCP连接
  6. clientSocket.connect((serverName, serverPort))
  7. sentence = input('Input lowercase sentence: ')
  8. # 只需要将数据送入TCP套接字,无需指定服务端地址
  9. clientSocket.send(sentence.encode())
  10. modifiedSentence = clientSocket.recv(1024)
  11. print('From Server: ', modifiedSentence.decode())
  12. clientSocket.close()

TCPServer:

  1. from socket import *
  2. serverPort = 12000
  3. serverSocket = socket(AF_INET, SOCK_STREAM)
  4. serverSocket.bind(('', serverPort))
  5. # 等待客户TCP连接请求,1为请求连接的最大数
  6. serverSocket.listen(1)
  7. print('The server is ready to receive')
  8. while True:
  9. # accept()将创建一个connectionSocket和特定用户交互
  10. connectionSocket, addr = serverSocket.accept()
  11. sentence = connectionSocket.recv(1024).decode()
  12. capitalizedSectence = sentence.upper()
  13. connectionSocket.send(capitalizedSectence.encode())
  14. connectionSocket.close()