以下为个人学习笔记和习题整理
课程:哈尔滨工业大学 计算机网络
https://www.bilibili.com/video/BV1Up411Z7hC?share_source=copy_web


网络应用与单机应用的本质不同:

网络应用需要有 网络的基础环境 ,一部分软件运行在自己机器上(如浏览器),另一部分软件(或数据信息)运行在互联网的某个地方(如某些服务器),两部分软件需要 进行交互 ,才共同构成了网络应用。

既然网络应用是由不同的部分构成的,那么它就存在一个 结构

# 网络应用的体系结构

现代网络应用中,有两种主流的体系结构。

# 客户机 / 服务器结构

主从式架构(英语:Client–server model)也称 客户端/服务器架构C/S架构 ,是一种网络架构,它把客户端(Client,通常是一个采用图形用户界面的程序),与服务器(Server)区分开来。每一个客户端软件的实例都可以向一个服务器或应用程序服务器发出请求。有很多不同类型的服务器,例如文件服务器、游戏服务器等。

  • 服务器 (server)
    1. 7 * 24小时 提供服务
    2. 永久性 访问地址 / 域名
    3. 利用大量服务器实现可扩展性(数据中心,能够处理大量的并发请求)
  • 客户端 (client)
    1. 与服务器通信,使用服务器提供的服务
    2. 间歇性 接入网络
    3. 可能使用 动态IP地址
    4. 不会与其他 “客户机” 直接通信

主从式架构通过不同的途径应用于很多不同类型的应用程序,最常见就是目前在因特网上用的 网页 。例如,当你在维基百科阅读文章时,你的电脑和网页浏览器就被当做一个 客户端 ,同时,组成维基百科的电脑、数据库和应用程序就被当做 服务器 。当你的网页浏览器向维基百科请求一个指定的文章时,维基百科服务器从维基百科的数据库中找出所有该文章需要的信息,结合成一个网页,再发送回你的浏览器。

# 点对点结构

对等式网络(英语:peer-to-peer, 简称 P2P ),又称 点对点技术 ,是无中心服务器、依靠用户群(peers)交换信息的互联网体系,它的作用在于,减低以往网路传输中的节点,以降低资料遗失的风险。与有中心服务器的中央网络系统不同,对等网络的每个用户端既是一个节点,也有服务器的功能,任何一个节点无法直接找到其他节点,必须依靠其户群进行信息交流。

  • P2P 架构的特点
    1. 没有永远在线的服务器
    2. 任意端系统 / 节点之间可以 “直接” 通讯
    3. 节点间歇性接入网络
    4. 节点可能改变 IP 地址

P2P 节点能遍布整个互联网,也给包括开发者在内的任何人、组织或政府带来监控难题。P2P 在 网络隐私要求高文件共享 领域中,得到了广泛的应用。使用一般型 P2P 技术的网络系统有比特币、Gnutella 或自由网等。另外,P2P 技术也被使用在类似 VoIP 等实时媒体业务的数据通信中。有些网络(如 Napster 、OpenNAP、IRC @find)使用 客户端-服务器结构 实现包括搜索的一些功能,而使用 P2P结构 来实现另外一些功能。这种网络设计模型不同于客户端 - 服务器模型,在客户端 - 服务器模型中通信通常来往于一个中央服务器。

# 混合结构(Hybrid)

将两种结构混合在一起使用,利用两者的优点同时规避两者的缺点。如 Napster

Untitled

# 网络应用进程通信

# 进程间通信

进程间通信是网络应用的基础,而 进程 是主机上运行的 程序

  • 运行在 同一主机上 的进程之间通过由操作系统提供的 进程间通信机制 进行通信;

  • 运行在 不同主机上 的进程之间通过 消息交换(报文交换) 进行通信。(★)

    任一特定的情景下,互相通信的一对进程总是可以被分为

    • 客户机进程 (client process): 发起通信 的进程;
    • 服务器进程 (server process): 等待通信请求 的进程。

    采用 P2P架构 的应用也需要通过 “消息交换”,同样存在客户机进程与服务器进程之分。

# 消息交换的实现

网络应用的信息交换实际上是 进程间的消息交换 (通过 socket 套接口),需要实现对 进程的寻址 (IP 地址 + 端口号),消息的具体交换遵循的是 应用层协议 (如 HTTP、SMTP)。

  1. Socket 套接字:进程间通信利用 socket 发送 / 接受信息实现(★)

    1. 可以类比于寄信,socket 套接字接口是 “门” ,而硬件基础设施、网络协议栈(传输层及以下)等是 “门外” 的 传输基础设施

      • 发送方将消息送到门外邮箱
      • 发送方依赖(门外的)传输基础设施将消息传到接收方所在主机,并送到接收方的门外
      • 接收方从门外获取消息

      Untitled

    2. 操作系统 向进程提供 API(应用编程接口,即套接字 socket)

    3. 应用程序员能控制 socket 应用层端 的所有细节,但对于 socket 传输层端 只有很少的控制,其支持

      • 传输层协议 的选择(TCP 或 UDP)(★)
      • 可能有的几个 传输层参数 的设置(如最大缓冲区、最大 segment 长度)
  2. 进程寻址:实现不同主机上的进程间通信,每个进程必须拥有 标识符

    • 网络层上的 IP地址 ,能唯一标识 Internet 上的一台主机;
    • 操作系统为主机上每个需要通信的进程分配了一个 端口号(Port number)

    因此,进程的标识符由 IP 地址 + 端口号 组成,能唯一标识一个 “网络上的进程”。

    Untitled

    使用特定知名协议的应用,有其约定的端口号,不能随便使用(其他 0~65536 可用来做自己的网络应用)。

    • HTTP Server :80(Web 应用)
    • Mail Server :25
  3. 应用层协议:网络应用需遵循应用层协议,完成消息的具体交换。
    网络应用可根据所使用的协议分为两类,

    1. 公开协议 :由 RFC(Request For Comments) 定义,公开的标准、规范,允许互操作。如 HTTP , SMTP
    2. 私有协议 :多数 P2P 文件共享应用
    • 应用层协议的内容:(协议三要素)
      • 消息的 类型(type) :如请求消息 / 响应消息?
      • 消息的 语法(syntax) :消息中有哪些字段(fields)?每个字段如何描述?
      • 字段的 语义(semantics) :字段中信息的含义。
      • 规则(rules) :进程何时发送 / 响应消息,进程如何发送 / 响应消息。

# 传输层所提供的服务

消息交换不是应用层自己做的, 传输层 及之下的各层共同完成传输服务。

# 网络应用对传输服务的需求

传输层可提供的服务大致地可分为三类:

  1. 可靠数据传输(reliable data transfer)
    • 某些网络应用能够容忍一定的数据丢失。
      • 网络电话,网络视频
    • 某些网络应用要求 100% 可靠的数据传输。
      • 文件传输,telnet
  2. 时间(timing)
    • 有些应用只有在延迟足够低时才 “有效”。
      • 网络电话,网络游戏
  3. 吞吐量(throughput)
    • 某些应用只有在带宽达到最低要求时才 “有效”。如网络视频
    • 某些应用能够适应任何带宽 —— 弹性应用(elastic) 。如 email,为异步应用,没有太多时间上的要求。
  4. 安全性(security)

# Internet 提供的传输服务

  • TCP 服务
    • 面向连接 :客户机 / 服务器进程间需要建立连接(全双工)
    • 可靠传输 :能够把底层的不可靠转变为可靠。
    • 流量控制 :发送方不会发送速度过快,超过接收方的处理能力
    • 拥塞控制 :当网络负载过重时能够限制发送方的发送速度(对整个网络起作用)
    • 不提供时间 / 延迟保障
    • 不提供最小带宽保障
  • UDP 服务
    • 无连接
    • 不可靠的数据传输
    • 不提供:可靠性保障、流量控制、拥塞控制、延迟保障、带宽保障

UDP 这么多功能都不提供,为什么使用?

答:UDP 服务做了任何一个传输层服务都要做的基本的事,除此之外不做任何事。它提供了最大的 “自由”,即网络层基本的服务穿透过来了,留给 “应用程序” 发挥的空间,即掌控数据传输的能力。(后面会学到的 QUIC 协议便是基于 UDP 的)

# Web 应用

# 万维网(World Wide Web)

最基本的构成要素是 网页(Web Page) ,所有的网页之间互相链接。网页包含多个 对象(objects) ,其构成为

  • 对象 :HTML 文件、JPEG 图片、视频文件、动态脚本等,丰富多彩;
  • 基本HTML文件 :包含对其他对象 引用 的链接,是每个网页都有的。

对象的寻址通过 URL(Uniform Resoure Locator, 统一资源定位器)

  • 基本格式: Scheme://host:port/pathScheme 为协议,省略时默认为 http:// ,host 为主机 (域名 / IP 地址),port 为端口号,path 为路径。

  • URL 提供了一种机制,使得万维网上所有的资源都有了 唯一的标识符 ,由此它们之间可以互相链接。

# HTTP 协议

万维网应用所遵循的协议,称为 超文本传输协议(HyperText Transfer Protocol) 。协议采用的是 客户机/服务器架构 ,其

  • 客户端浏览器(Browser) ,请求、接收、展示 Web 对象;
  • 服务器Web Server ,响应客户的请求,发送对象。

# HTTP 使用的传输层协议:TCP

浏览器 (HTTP 客户端) 与服务器 (HTTP 服务器) 的通信过程:

  1. 服务器在 80 端口 等待客户的请求
  2. 浏览器发起 到服务器的 TCP 连接
  3. 服务器接受 来自浏览器的 TCP 连接
  4. 浏览器与 Web 服务器交换 HTTP 消息
  5. 关闭 TCP 连接

HTTP 应用协议是一个 无状态协议 :服务器不维护任何有关客户端过去所发请求的信息。

有状态的协议更复杂:

  • 需维护状态(历史信息);
  • 如果 client 或 server 失效,会产生状态的不一致,解决这种不一致代价高。

# HTTP 连接的两种类型

对 TCP 的两种使用方法:

  • 非持久性连接(Nonpersistent HTTP) :每个 TCP 连接 最多允许传输一个对象 ,HTTP 1.0 版本使用非持久性连接。
  • 持久性连接(Persistent HTTP) :每个 TCP 连接 允许传输多个对象 ,HTTP 1.1 版本默认使用持久性连接。

# 非持久性连接过程

假定用户在浏览器中输入 URL http://www.someschool.edu/someDepartment/home.indexhome.index 包含文本和 10 个 指向 jpeg 图片的链接。

Untitled

# 响应时间分析与建模

定义 往返时间 RTT (Round Trip Time) 为从客户端发送一个 很小的数据包 到服务器并返回所经历的时间(包括分组的传输时延、排队时延和处理时延)。则从浏览器输入 URL 回车(发送请求)到最后得到文件的 响应时间 (Response time) 包括:

  • 发起、建立 TCP 连接 :1 个 RTT
  • 发送 HTTP 请求消息 到 HTTP 响应消息的 前几个字节到达 :1 个 RTT
  • 响应消息中所含的文件 / 对象传输时间

于是,总的响应时间为:

ttotal =2×RTT+ 文件发送时间 t_{\text {total }}=2 \times R T T+\text { 文件发送时间 }

# 非持久性连接的问题

  • 每个对象需要 2个RTT
    • 理论上,该问题总共需要 2+10×2=222 + 10 \times 2 = 22 个 RTT
  • 操作系统需要为每个 TCP 连接 开销资源 (overhead)
  • 浏览器会打开多个 并行 的 TCP 连接以获取网页所需对象,但这会给服务器带来巨大的负担。

TCP 连接是 宝贵的资源 ,建立 TCP 连接是有代价的。

# 持久性连接

发送响应后,服务器保持 TCP 连接的打开,后续的 HTTP 消息可以通过这个连接发送。

按照是否采用 流水机制(pipelining) ,持久性连接可分为:

  • 无流水机制 的持久性连接:客户端只有收到前一个响应后才发送新的请求, 每个被引用的对象 耗时 1 个 RTT。

    • 理论上,该问题总共需要 2+10×1=122 + 10 \times 1 = 12 个 RTT
  • 带有流水机制 的持久性连接:客户端只要遇到一个引用对象就尽快发出请求,HTTP 1.1 的默认选项。

    理想情况下,收到所有的引用对象只需耗时约 1个RTT

    • 理论上,该问题总共需要 2+1=32 + 1 = 3 个 RTT

# HTTP 的消息格式

HTTP 协议有两类消息: 请求消息响应消息 ,均采用 ASCII 码编写,供人类直接阅读。

# 请求消息 (request)

Untitled

  1. Request line 请求行:各版本的 method 方法,

    • HTTP/1.0: GETPOSTHEAD
    • HTTP/1.1:除上述三种外,增加了 PUTDELETE
    • HEAD :请求服务器不要将所请求的对象放入响应消息中;(用作测试)

    • PUT :将消息体中的文件上传到 URL 字段所指定的路径;

    • DELETE :删除 URL 字段所指定的文件。

  2. Header lines 头部行

    Untitled

  3. Entity body 消息体

    上传输入的方法:从客户端(cilent)到服务器(server)

    • POST 方法:在请求消息的 消息体 (entity body) 中上传客户端的输入。
    • URL 方法:使用 GET 方法,输入信息通过 request line 的 URL 字段 上传,适用于信息较少的情况。

# 响应消息 (response)

Untitled

  1. Status line 状态行: status code 响应状态代码。

  2. Header lines 头部行

    Untitled

HTTP 是无状态协议,但很多应用需要服务器掌握客户端的状态(会话状态,如网上购物)。

Cookie 是某些网站为了 辨别用户身份 、进行 session 跟踪 ,而存储在用户本地终端上的数据(通常经过加密)。

  1. Cookie 的组件(架设在 HTTP 上)
    1. HTTP 响应消息的 cookie 头部行

    2. HTTP 请求消息的 cookie 头部行

      可见,HTTP 消息的头部行是 可扩展的

    3. 保存在客户端主机上的 cookie 文件,由浏览器管理

    4. Web 服务器端的后台数据库

  2. Cookie 的原理(通信过程)
    服务器端将在客户端初次访问时为其创建 cookie ID(存放在后台数据库),并在返回的响应中增加 Set-cookie 头部行。之后客户端的每次请求中,都带有 cookie 的头部行,服务器收到含有 cookie 头部行的请求,将执行 cookie-specific 即用户特定的动作,以根据客户的状态提供相应的信息。cookie 存储在用户本地终端上,所以一段时间后再次和服务器通信时,服务器仍能读取该客户端的状态。

Untitled

  1. Cookie 的作用:身份认证,保留购物车、推荐等用户会话状态信息。

# Web 缓存 / 代理服务器技术

不访问服务器的前提下满足客户端的 HTTP 请求。

为什么要发明这种技术?(性能角度,而 cookie 是从功能角度)

  • 缩短客户请求的响应时间
  • 减少机构 / 组织的流量
  • 在大范围内(Internet)实现有效的内容分发
  1. 客户端使用代理服务器的过程:
    Untitled

    • 用户设定浏览器通过 缓存(代理服务器) 进行 Web 访问
    • 浏览器向代理服务器发送 所有的HTTP请求
      • 如果所请求对象在缓存中(称为 缓存命中 ),缓存返回对象
      • 否则,缓存服务器向 原始服务器 发送 HTTP 请求,获取对象,然后返回给客户端并保存该对象

    代理服务器(缓存)既充当 客户端 ,也充当 服务器 。一般由组织或 ISP(Internet 服务提供商)架设。

  2. 性能分析
    Untitled

    代理服务器,也是计算机领域中广泛使用的 缓存技术 (具有普遍性的设计思想)的一种实现。

  3. 解决同步问题(存放在代理服务器的对象副本可能是陈旧的)

    HTTP 协议中的 条件GET (conditional GET) 方法:如果缓存有最新的版本,则不需要发送请求对象

    • 代理服务器:在 HTTP 请求消息中声明 所持有版本 的日期。
      • If-modified-since: <date>
    • 原始服务器:如果缓存的版本是最新的,则响应消息中 不包含对象
      • HTTP/1.0 304 Not Modified

# Email 应用

# Email 应用的构成组件

  1. 邮件客户端 (user agent)

    • 读、写 Email 消息(网络应用,也有 Web 形式 的客户端,如 QQ-Mail)
    • 与服务器交互,收、发 Email 消息
  2. 邮件服务器 (Mail server)

    • 邮箱 :存储发给该用户的 Email

      不在线仍然可以发邮件,存储在邮件服务器

    • 消息队列(message queue) :存储等待发送的 Email

    采用 Mail Server ,而不是客户端之间直接发送 Email 的原因:

    • 邮件客户端(手机 / 电脑)不能保证 7 * 24 小时在线
    • 给别人发送可能失败

    Email 应用是典型的 “异步” 应用 ,即 发送方发送接收方接受 并不需要同时。

  3. SMTP 协议 (Simple Mail Transfer Protocol)

    • 邮件服务器 之间传递消息所使用的协议(★)
      • 客户端:发送消息的服务器
      • 服务器:接收消息的服务器

# SMTP 协议

使用 TCP 进行 Email 消息的可靠传输(端口 25)

  • 传输过程的三个阶段:握手消息的传输关闭

  • 命令 / 响应交互模式

    • 命令(command) :ASCII 文本

      由于历史原因,Email 消息只能包含 7 位 ASCII码

      Email 是非常古老的应用,在设计之初并没有多媒体,只有文本。

    • 响应(response) :状态代码和语句

    服务器与客户端交互过程示例:
    Untitled

    1. SMTP 协议的特点:

      • 使用 持久性连接 (TCP 协议)
      • 要求消息必须由 7 位 ASCII 码 构成
      • SMTP 服务器利用 CRLF.CRLF 确定消息的结束
    2. STMP 与 HTTP 对比:

      • 都使用 命令/ 响应 交互模式 ,命令和状态代码都是 ASCII 码
      • HTTP 协议: 拉式(pull) ,把网页 “拉” 回本地;每个对象封装在独立的响应消息中。
      • SMTP 协议: 推式(push) ,发出 Email 邮件信息;多个对象在由多个部分构成的消息中发送。

# Email 的消息格式

  • SMTP 协议:Email 消息的传输 / 交换协议(RFC 822:文本消息格式标准)

    • 头部行(header)ToFromSubject(邮件主题),与 SMTP 命令不同
    • 消息体(body) :消息本身,只能是 ASCII 字符
  • MIME 协议:多媒体邮件扩展(RFC 2045, 2056)

    • 通过在邮件头部 增加额外的行 以声明 MIME 的内容类型

      Untitled

    回顾 MIME 协议以及 cookie 的实现:

    • 通过在消息的 头部行 中,增加新的行实现对应用的 拓展
    • 计算机领域中, 编码解码 应用也在网络中被普遍使用。

# 邮件访问协议:从服务器获取邮件

一个应用可以使用 不止一个协议

  • 邮件客户端向邮件服务器 发送邮件 :使用 SMPT
  • 邮件客户端从邮件服务器 接收邮件 :使用 “邮件访问协议”。
  1. POP 协议(无状态协议): 邮局协议(Post Office Protocol) ,是 TCP/IP 协议族中的一员。

    • 主要用于支持使用客户端远程管理在服务器上的电子邮件。(认证 / 授权和下载,认证过程事务阶段

      Untitled

    • POP 支持 离线邮件处理 ,其具体过程是:邮件发送到服务器上,电子邮件客户端调用邮件客户机程序以连接服务器,并下载所有未阅读的电子邮件。

      • 这种离线访问模式是一种 存储转发 服务,将邮件从邮件服务器端送到个人终端机器上,一般是 PC 机或 Mac。

        一旦邮件下载到 PC 机或 Mac 上,邮件服务器上的邮件将会 被删除

      • 但目前的 POP3 邮件服务器大都可以 “只下载邮件,服务器端并不删除” ,也就是改进的 POP3 协议。

        • “下载并删除” 模式:用户如果换了客户端软件,无法重读该邮件
        • “下载并保持” 模式:不同客户端都可以保留消息的拷贝
    • 最新版本为 POP3

  2. IMAP 协议(有状态协议): 因特网信息访问协议Internet Mail Access Protocol),是一个应用层协议,用来从 本地邮件客户端 (如 Microsoft Outlook、Foxmail)访问远程服务器上的邮件。

    相较于 POP3,更多功能、更加复杂、能够操纵服务器上存储的消息。

    • 所有消息统一保存在一个地方:服务器
    • 允许用户利用文件夹组织消息
    • IMAP 支持跨会话(Session)的用户状态
  3. HTTP 协议:浏览器本身也是一种邮件客户端,基于 Web 的 email 应用如 163、QQ Mail 等。

# DNS 服务

# 概述

域名系统(英语:Domain Name System,缩写: DNS )是互联网的一项服务,它作为将 域名IP 地址 相互映射的一个 分布式数据库 ,能够使人更方便地访问互联网。(IP 地址本身是数字,不易于人类使用,而域名相对来说可读性更好)

  • DNS 域名解析系统,是由多层命名服务器构成的 分布式数据库
  • DNS 本身也是 应用层协议 ,由应用层上的软件负责完成名字的解析,
    • Internet 的核心功能,用应用层协议实现
    • 网络边界复杂,分布式而不使用集中式的原因:
      集中式存在单点失败问题、流量问题、距离问题和维护性问题,不可伸缩,不适合。
  • DNS 提供的服务:
    • 域名IP 地址的翻译
    • 别名服务:主机别名、邮件服务器别名
    • 负载均衡:Web 服务器,提供多个映射

# 分布式层次式数据库

客户端想要查询 www.amazon.com 的 IP 地址:

Untitled

  1. 客户端查询 根服务器 ,找到 com 域名解析服务器
  2. 客户端查询 com 域名解析服务器 ,找到 amazon.com 域名解析服务器
  3. 客户端查询 amazon.com 域名解析服务器 ,获得 www.amazon.com 的 IP 地址
  • 根域名服务器 (Root DNS servers)

    • 本地域名解析服务器 无法解析域名时,访问 根域名服务器
    • 根域名服务器如果不知道映射,则访问权威域名服务器获得映射,再向本地域名服务器返回映射。

    Untitled

  • 顶级域名服务器 TLD (Top-Level Domain)
    负责 comorgnetedu 等顶级域名和 cn, uk, fr 等国家顶级域名

    • Network Solutions 维护 com 顶级域名服务器
    • Educause 维护 edu 顶级域名服务器
  • 权威 (Authoritative) 域名服务器:组织的域名解析服务器,提供组织内部服务器 (本地化,自治) 的解析服务。

    • 组织自己负责维护,或委托
    • 服务提供商负责维护
  • 本地域名解析服务器不严格属于 层级体系)

    • 由 ISP 提供,每个 ISP 都有一个本地域名服务器,又称默认域名解析服务器
    • 当主机进行 DNS 查询时,查询被发送到本地域名服务器,作为代理将查询转发给 (层级式) 域名解析服务器系统,或利用缓存

# DNS 查询

存在两种查询方式:

  1. 迭代查询:被查询服务器返回域名解析服务器的名字

  2. 递归查询:将域名解析的任务交给所联系的服务器

    Untitled

# DNS 记录缓存和更新

只要域名解析服务器获得 域名-IP 映射 ,即 缓存 这一映射

  • 一段时间过后,缓存条目失效(删除)
  • 本地域名服务器 一般会缓存顶级域名服务器的映射,因此根域名服务器 不经常被访问

# DNS 记录和消息格式

  • 资源记录 (RR, resource records)RR format: (name, value, type, ttl)

    不同的类型对 namevalue 的解释不同:

    Type 解释 Name Value
    A 最基本的主机到 IP 地址的映射 主机域名 IP 地址
    NS 权威域名解析服务器 域(如 edu.cn 该域权威域名解析服务器的主机域名
    CNAME 实现别名服务 某一真实域名的别名 Value:真实域名
    MX 邮件服务器 与 name 相对应的邮件服务器
  • 消息格式

    • DNS 协议: 查询/回复 模式,查询(query)和回复(reply)的 消息格式相同
    • 消息头部
      • Identification :16 位查询编号,回复使用相同的编号

      • flags :查询或回复、期望递归、递归可用、权威回答

        Untitled

# P2P 应用

# 文件分发场景

C/S 架构 v.s. P2P 架构 :从一个服务器向 N 个节点分发一个文件需要多长时间?

Untitled

  1. C/S 架构 :服务器 串行地 发送 N 个副本

    • 完成文件分发所需的时间:Dcs=max{NFus,Fdmin}D_{c s}=\max \left\{\frac{N F}{u_{s}}, \frac{F}{d_{\min }}\right\}
  2. P2P 架构 :服务器必须发送一个副本。而拥有该文件的一部分的结点可以 共同协助 将文件上传到 Internet 上。

    • 完成文件分发所需的时间:DP2P=max{Fus,Fdmin,NFus+i=1Nui}D_{\mathrm{P} 2 \mathrm{P}}=\max \left\{\frac{F}{u_{s}}, \frac{F}{d_{\min }}, \frac{N F}{u_{s}+\sum_{i=1}^{N} u_{i}}\right\}

    随着网络中连接的结点数 N 的增大, C/S 架构 所需的时间线性增长,而 P2P 架构 则越往后越 “平”,存在上界。

    可见, 文件分发场景 适合使用 P2P 架构

    Untitled

# 索引技术

P2P 系统的索引,即 信息节点位置(IP地址+端口号) 的映射。

  • 集中式索引 :内容和文件传输是分布式的,但是内容定位是高度集中式的(由一台中央目录服务器负责索引)。

    存在的问题:单点失效问题、性能瓶颈、版权问题

  • 洪泛式查询(Query flooding) :完全分布式架构,每个节点对它共享的文件进行索引,且只对它共享的文件进行索引。

    • 覆盖网络 (overlay network): Graph

      1. 节点 X 与 Y 之间如果有 TCP 连接,那么构成一个边(虚拟链路)
      2. 所有的活动节点和边构成覆盖网络。

      查询消息通过已有的 TCP 连接发送,节点转发查询消息。

      如果查询命中,则利用反向路径发回查询节点,最后请求查询的主机和命中主机建立 TCP 连接。

      像洪水一般在网络中 “泛滥”,会给网络带来负担。

  • 层次式覆盖网络 :介于集中式索引和洪泛查询之间的方法

    • 每个节点或者是一个 超级节点 ,或者被分配一个超级节点(普通结点),超级节点负责跟踪子节点的内容(提供索引)
      1. 节点和超级节点间维持 TCP 连接(分层式)
      2. 某些超级节点对之间维持 TCP 连接(洪泛式、分布式)

P2P 网络应用的通信过程的实质:C/S 进程之间的通信。

  • P2P 应用程序结构:部分实现 server/cilent 功能:多线程,多进程等
  • P2P 网络应用是否适合基于 DNS 实现 peer 寻址?
    不适合。动态 IP 地址影响时刻更新 DNS,需要 DNS 处理能力很强。

# socket 编程

socket 是一种 操作系统 提供的 进程间通信机制

在操作系统中,通常会为 应用程序 提供一组 应用程序接口(API) ,称为套接字接口(英语:socket API)。

  • 最初设计:socket API 来源于 Unix-Berkley 的项目,是面向 TCP/IP 协议栈的接口(当前可以面向多个协议栈)。
  • 目前:事实上的工业标准,绝大多数 OS 均支持,是 Internet 网络应用最典型的 API 接口。
  • 通信模型:客户机 / 服务器模型(C/S),是应用进程间通信的抽象机制。

    socket 一词的来历:就像一个 “插座” ,两者之间一插就可以通信。

# 应用编程接口 API

应用进程的控制权和操作系统的控制权进行转换的一个 系统调用 接口。

  • 应用进程将 控制权 交给操作系统(系统调用),操作系统执行相应的过程,并将结果返回给应用进程。

    Untitled

# 三种典型的 API

  • Berkeley UNIX 操作系统 定义的一种 API,称为套接字接口(socket interface),简称套接字(socket)。

    最具有代表性,应用最广泛的标准的伯克利套接字。

  • 微软在 socket 的基础上扩展形成的一个稍有不同的 API,称为 WINSOCK (Windows Socket Interface)。

    Unix / Linux 使用的是标准的伯克利套接字,而 windows 使用的是 WINSOCK ,两者之间有很大部分重叠。

  • AT&T 为其 UNIX V 定义了一种 API,简写为 TLI (Transport Layer Interface)传输层接口。

# 应用进程通信的寻址问题

  • 标识通信端点(对外)
    • IP 地址 + 端口号 (又称 “端点地址”)
  • 操作系统如何管理套接字(对内)
    • 套接字描述符 (socket descriptor):小整数
    • socket 抽象:当应用进程 创建套接字 时,操作系统分配一个 数据结构 存储该套接字相关信息,并返回套接字描述符

# socket API 函数

函数名 函数功能 适用条件
WSAStartup() 初始化 socket 库 仅对 WinSock
WSACleanup() 清除 / 终止 socket 库的使用 仅对 WinSock
socket() 创建套接字
closesocket() 释放 / 关闭套接字 在 Unix / Linux 中为 close() ,与关闭文件相同
bind() 绑定套接字的本地 IP 地址和端口号 通常客户端不需要,由操作系统自动完成
listen() 置服务器端 TCP 套接字为监听模式,并设置队列大小 仅用于服务器端 TCP 套接字
connect() “连接” 远端服务器(UDP 实际上没有连接) 仅用于客户端
accept() 接受 / 提取一个 TCP 连接请求,创建新套接字,通过新套接字通信 仅用于服务器端 TCP 套接字
send() 发送数据 用于 TCP 套接字 或 连接模式的客户端 UDP 套接字
sendto() 发送数据报 用于非连接模式的 UDP 套接字
recv() 接收数据 用于 TCP 套接字 或 连接模式的客户端 UDP 套接字
recvfrom() 接收数据报 用于非连接模式的 UDP 套接字
setsockopt() 设置套接字选项参数
getsockopt() 获取套接字选项参数

# socket 编程示例

We’ll use the following simple client-server application to demonstrate socket programming for both UDP and TCP :

  1. The client reads a line of characters (data) from its keyboard and sends the data to the server.
  2. The server receives the data and converts the characters to uppercase.
  3. The server sends the modified data to the client.
  4. The client receives the modified data and displays the line on its screen.

# Socket Programming with UDP

  1. The client-server application using UDP :

    Untitled

    # UDPClient.py
    from socket import *
    serverName = 'hostname'
    serverPort = 12000
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    message = input('Input lowercase sentence:')
    clientSocket.sendto(message.encode(), (serverName, serverPort))
    modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
    print(modifiedMessage.decode())
    clientSocket.close()
    # UDPServer.py
    from socket import *
    serverPort = 12000
    serverSocket = socket(AF_INET, SOCK_DGRAM)
    serverSocket.bind(('', serverPort))
    print("The server is ready to receive")
    while True:
        message, clientAddress = serverSocket.recvfrom(2048)
        modifiedMessage = message.decode().upper()
        serverSocket.sendto(modifiedMessage.encode(), clientAddress)

# Socket Programming with TCP

  1. TCP Server 欢迎套接字(welcome socket)连接套接字(connection socket)

    Untitled

  2. The client-server application using TCP :

    Untitled

    # TCPClient.py
    from socket import *
    serverName = 'servername'
    serverPort = 12000
    clientSocket = socket(AF_INET, SOCK_STREAM)
    clientSocket.connect((serverName,serverPort))
    sentence = input('Input lowercase sentence:')
    clientSocket.send(sentence.encode())
    modifiedSentence = clientSocket.recv(1024)
    print('From Server: ', modifiedSentence.decode())
    clientSocket.close()
    # TCPServer.py
    from socket import *
    serverPort = 12000
    serverSocket = socket(AF_INET,SOCK_STREAM)
    serverSocket.bind(('',serverPort))
    serverSocket.listen(1)
    print('The server is ready to receive')
    while True:
        connectionSocket, addr = serverSocket.accept()
        sentence = connectionSocket.recv(1024).decode()
        capitalizedSentence = sentence.upper()
        connectionSocket.send(capitalizedSentence.encode())
        connectionSocket.close()