徐州市网站建设_网站建设公司_Bootstrap_seo优化
2025/12/29 9:58:47 网站建设 项目流程

第2章应用层

应用层 概述

一、章节基本信息

  • 章节主题:第 2 章 应用层
  • 授课 / 改编方:中国科学技术大学 自动化系 郑烇
  • 参考教材:《Computer Networking: A Top-Down Approach》(第 7 版),Jim Kurose、Keith Ross 著,Addison-Wesley,April 2016

二、章节定位

本节课是 “自顶向下” 学习计算机网络的开篇,聚焦网络的最高层(应用层),本章包含原理、实例、编程三个核心部分,是应用层后续内容的总览。

三、章节内容构成

  1. 原理部分:2.1 应用层协议原理
  2. 实例部分(互联网流行应用 + 对应协议):
    • 2.2 Web and HTTP(Web 应用 + HTTP 协议)
    • 2.3 FTP*(FTP 应用 + FTP 协议)
    • 2.4 Email(电子邮件应用 + SMTP/POP3/IMAP 协议)
    • 2.5 DNS(域名解析应用 + DNS 协议)
    • 2.6 P2P 应用
    • 2.7 CDN(内容分发网络)
  3. 编程部分:2.8 TCP 套接字(Socket)编程、2.9 UDP 套接字编程

四、应用层的主要目标(对应课件 “目标” 部分)

掌握计算机网络应用的原理、网络应用协议的概念及实现,具体如下:

五、应用层与传输层的关联

  • 应用层无法独立完成报文交换,需借助传输层提供的服务实现。
  • 传输层向应用层提供的服务,通过 “服务模型(service model)” 描述其指标体系。
  • 应用的交互模式:客户 - 服务器(CS)模式、对等(P2P)模式。

六、socket API 的作用

在 TCP/IP 架构中,传输层与应用层的接口形式是 socket API(套接字应用程序接口)

  • 传输层通过 socket API 向应用层提供服务
  • 应用层通过 socket API 调用传输层服务,对应本章的 TCP、UDP 套接字编程内容

七、网络应用的实例扩展

除本章重点讲解的应用外,互联网常见应用还包括:

八、创建新网络应用的要点

编程层面

  • 在不同端系统上运行应用进程
  • 通过网络基础设施提供的服务,实现应用进程间的通信(例如 Web 的服务器软件与浏览器软件通信)

网络核心的特点

  • 网络核心中没有应用层软件及功能
  • 网络应用仅存在于端系统中,这一设计利于网络应用的快速开发与部署

2.1 应用层协议原理

2.1.1应用层的重要性与创新特性

(1)应用层协议数量最多的原因

互联网架构支持自定义各类应用协议,只需通过编程实现协议即可部署网络应用,具备极强的灵活性和创造力。例如早期的 Email、FTP、Web,后续的 P2P 文件共享、多媒体应用、电子支付、网络游戏等,均基于此架构快速落地。

(2)应用部署门槛低,创新效率高

  • 部署方式简单:编程序后,购买 / 租用主机运行服务器端,客户端软件可挂载到分享平台供用户下载(如 Web 应用只需搭建 Web 服务器,客户端通过浏览器访问)。
  • 核心无应用介入:网络核心(如路由器)最高仅到网络层,应用仅需在端系统(终端设备)部署,无需修改网络核心设备,部署速度极快。

(3)国内互联网应用创新的领先地位

  • 从模仿到引领:早期国内应用(如 QQ)借鉴国外产品,如今在电商(淘宝、京东 vs 亚马逊)、网络直播、即时通讯(微信)等领域,用户体验和业务规模远超国外同类产品。
  • 创新领域广泛:涵盖共享单车、网约车、网络直播带货等,用户规模和业务量全球领先。
  • 支撑基础:国内持续投入高等教育和职业教育,每年培养数百万工科大学生,为应用创新提供人才保障。

2.1.2网络应用的体系结构

按应用进程的通信方式,网络应用架构分为三类,核心是 “应用进程间如何交互与共享资源”。

(1)客户 - 服务器模式(C/S 模式)

①核心原理
  • 服务器特性:① 先启动且持续运行;② 固定 IP 地址和知名端口号(约定俗成,如 HTTP 用 80、FTP 用 21),便于客户端定位;③ 资源集中(软件、硬件、数据均在服务器)。
  • 客户端特性:① 后启动,主动向服务器请求资源;② 间歇性连接互联网,可使用动态 IP(如笔记本通过 WiFi 获取 DHCP 动态地址);③ 无资源,依赖服务器响应获取服务;④ 不直接与其他客户端通信。
②优缺点
  • 优点:架构简单,资源集中管理,易于初期部署。
  • 缺点:
    • 可扩展性差:服务器性能达到阈值后,会出现 “断崖式下降”(而非平滑下降)。例如单服务器支撑几百客户端可行,支撑几十万客户端时,CPU、内存、网络出口任一环节都可能成为瓶颈,且无法扩展客户端附近的网络链路。
    • 可靠性差:所有客户端依赖单一(或少量)服务器,服务器宕机则整个服务不可用。

(2)对等模式(P2P 模式)

①核心原理
  • 节点特性:每个节点(Peer)既是客户端(请求其他节点资源),也是服务器(向其他节点提供自身资源),无固定中心服务器(或极少依赖)。
  • 动态性:节点间歇性上线 / 下线,每次上线可能获取新 IP;节点数量增加时,“请求资源的节点” 和 “提供资源的节点” 同步增加,天然具备扩展性。
②优缺点
  • 优点:
    • 可扩展性强:用户规模扩大时,服务能力同步提升(更多节点提供资源),性能维持在稳定水平,可支撑数百万用户(如迅雷、P2P 流媒体)。
  • 缺点:
    • 管理困难:需追踪节点上线 / 下线状态,且节点动态性强,难以统一管控。

(3)混合模式(C/S+P2P 结合)

①案例 1:Napster(P2P 文件分发系统)
  • 背景:美国西北大学本科生研发,初期用于校园网分发 MP3 音乐(解决 CD 成本高、FTP/Email 传输繁琐的问题)。
  • 架构细节:
    • 目录查询(C/S 模式):节点上线时向中心服务器注册(报告 IP 和共享的 MP3 列表);客户端下载前向中心服务器查询 “谁拥有目标音乐”,服务器返回拥有者 IP。
    • 文件传输(P2P 模式):客户端直接向拥有者节点请求文件,下载完成后,该客户端也向服务器注册,成为新的资源提供者。
  • 结局:因侵犯音乐版权被唱片商起诉,中心服务器关闭后服务终止,但技术形式被后续 P2P 系统借鉴(如迅雷、电驴 eDonkey)。
②案例 2:即时通讯(QQ、早期微信)
  • 注册与好友定位(C/S 模式):用户登录时向中心服务器注册 IP 和用户名,服务器维护 “用户 - IP” 映射;用户查看好友在线状态时,服务器返回好友 IP。
  • 聊天通信(P2P 模式):两个在线用户的聊天数据直接在节点间传输,无需经过中心服务器。

2.1.3分布式进程通信的核心问题

网络应用的本质是 “不同端系统上的应用进程远程通信”,需解决三个关键问题。

问题 1:进程的标识与寻址(“如何让对方找到我”)

(1)核心需求
  • 标识:进程需唯一区分于其他进程(如 “淘宝小二” 需知道用户的唯一地址才能发货)。
  • 寻址:标识需包含地址信息,确保能定位到目标进程(如 “淘宝 ID” 需转换为物理地址才能投递包裹)。
(2)TCP/IP 协议栈的解决方案:IP + 传输层协议 + 端口号
  • 三要素组合:
    1. 主机 IP:定位进程所在的端系统(如 “哪台电脑”)。
    2. 传输层协议:区分进程使用 TCP 还是 UDP(二者端口号空间独立)。
    3. 端口号:传输层引入的 16 位标识(0-65535),区分同一主机上的不同应用进程(如 HTTP 用 80、FTP 用 21,称为 “知名端口”;客户端用动态端口)。
  • 进程标识:用 “IP 地址 + 传输层协议(TCP/UDP) + 端口号” 唯一标识一个进程;一对进程的通信由两个 “端节点(end point)” 构成(如 “源 IP: 源端口” 和 “目标 IP: 目标端口”)。

问题 2:如何使用传输层提供的服务(“如何把报文传给对方”)

(1)核心需求

应用进程不能 “隔空发报文”,需通过层间接口(应用层与传输层的交互点)借助传输层服务,本质是 “如何高效传递报文及必要控制信息”。

(2)层间接口的关键信息

应用层向传输层传递的信息需包含三类:

  1. SDU(服务数据单元):即要传输的报文本身(“货物”)。
  2. 发送方标识:源进程的 “IP + 端口号”(便于接收方回复,如 “发件人地址”)。
  3. 接收方标识:目标进程的 “IP + 端口号”(便于传输层定位目标,如 “收件人地址”)。
(3)优化:Socket(套接字)—— 减少层间交互信息量

  • 核心思想:用一个整数(类似文件句柄)代表 “通信关系的本地标识”,避免每次发送都传递 “IP + 端口号” 等重复信息,便于操作系统管理。
  • TCP Socket(面向连接):
    • 标识 “四元组”:(源 IP、源 TCP 端口、目标 IP、目标 TCP 端口),代表两个进程的会话关系(类似 “长期通信的登记号”)。
    • 特性:建立连接后,应用进程通过 Socket 读写数据,操作系统自动映射到对应的四元组,无需每次指定地址(如打开文件后用句柄操作,而非每次指定文件路径)。
  • UDP Socket(无连接):
    • 标识 “二元组”:(本地 IP、本地 UDP 端口),仅代表 “本地进程的端节点”(因 UDP 无连接,每次发送可能指向不同目标)。
    • 特性:发送时需额外指定 “目标 IP + 目标 UDP 端口”(如偶尔寄快递需每次写收件人地址);接收时,传输层需将 “发送方 IP + 端口” 一并交给应用进程。

(4)Socket 的本质

  • 物理上是一个整数,逻辑上是应用层与传输层的 “门户”:发送进程将报文 “推出” Socket,传输层负责送达对方 Socket;接收进程从 Socket “接收” 报文。
  • 本地标识属性:Socket 仅在本地操作系统有效,对方和网络核心无需知道 Socket 值,仅需通过 IP 和端口号定位进程。

问题 3:如何定义应用协议(“进程间如何交互报文”)

(1)应用协议的核心作用

定义 “不同端系统上的应用进程如何交换报文”,需包含四部分规则:

  1. 报文类型:如请求报文(客户端发给服务器)、响应报文(服务器返回客户端)。
  2. 语法:报文中的字段格式(如 HTTP 请求行的 “GET /xxx HTTP/1.1” 格式)。
  3. 语义:字段取值的含义(如 HTTP 响应码 200 代表 “请求成功”,404 代表 “文件未找到”)。
  4. 时序与动作:进程何时发送报文、如何响应(如客户端先发请求,服务器接收后返回响应)。
(2)应用协议 ≠ 应用

应用协议是应用的 “网络交互部分”,完整应用还包括:用户界面(如浏览器界面)、本地 IO 操作(如读取本地文件)、业务逻辑(如电商的订单处理)。例如 Web 应用,除 HTTP 协议外,还需 HTML 文件解释、浏览器渲染等模块。

(3)应用协议的分类
  • 公开协议(Open Protocol):由 RFC 文档定义,协议细节公开,支持不同厂商 / 个人实现的应用互操作(如 HTTP、SMTP、FTP)。
  • 私有协议(专用协议):协议细节不公开,仅特定应用使用(如 Skype 的网络电话协议)。

2.1.4应用层对传输层服务的需求与互联网传输层服务

(1)应用层对传输层服务的性能指标要求

应用需根据自身特性,要求传输层提供不同质量的服务,核心指标包括四类:

指标 定义 应用需求差异
数据丢失率 传输过程中数据丢失的比例 ① 高可靠性需求(如文件传输、Email):需 100% 无丢失,否则文件损坏、邮件格式错乱;② 可容忍丢失(如实时音视频):丢失少量数据仅产生噪点 / 毛刺,不影响语义理解。
延迟 报文从发送端到接收端的时间差 ① 低延迟需求(如网络电话、游戏):延迟 > 1 秒会严重影响交互(如通话时 “同时说话”、游戏指令延迟);② 可容忍延迟(如文件传输):延迟仅影响速度,不影响可用性。
吞吐 单位时间内有效传输的数据量(带宽) ① 最小吞吐需求(如实时视频):需固定带宽(如 1Mbps),否则画面卡顿;② 弹性吞吐(如文件传输):带宽高则快,低则慢,不影响使用。
安全性 数据的机密性、完整性、可认证性 ① 高安全需求(如电子支付、登录):需加密传输(防止密码泄露)、验证身份(防止伪装);② 低安全需求(如普通文件下载):可明文传输。

(2)互联网传输层的两种核心服务:TCP 与 UDP

互联网传输层仅提供 TCP 和 UDP 两种服务,应用需根据自身需求选择。

①TCP 服务(面向连接、可靠传输)
  • 核心特性:
    1. 可靠传输:发送端数据 100% 送达接收端(无丢失、无乱序、无重复)。
    2. 流量控制:防止发送方 “淹没” 接收方(接收方处理慢时,通知发送方减速)。
    3. 拥塞控制:感知网络拥堵(如丢包)时,主动降低发送速率,避免网络瘫痪。
    4. 面向连接:通信前需建立连接(三次握手),连接持续期间会话关系稳定。
  • 不提供的服务:无时间保证(无法承诺延迟)、无最小吞吐保证、无安全性(明文传输)。
  • 适用场景:需高可靠性的应用(如 Web、Email、文件传输)。
②UDP 服务(无连接、不可靠传输)
  • 核心特性:
    1. 不可靠传输:不保证数据送达,可能丢失、乱序。
    2. 无连接:通信前无需建立连接,每个报文独立传输。
    3. 无额外控制:无流量控制、无拥塞控制,发送速率由应用决定。
  • 不提供的服务:无可靠性、无流量 / 拥塞控制、无时间 / 带宽保证、无连接建立。
  • 适用场景:对实时性要求高、可容忍丢失的应用(如网络电话、实时视频、游戏)。
③UDP 存在的必要性

  • 区分进程:IP 仅能区分主机,UDP 通过端口号区分同一主机上的不同进程,实现 “进程到进程” 通信。
  • 无需建立连接:事务性应用(如简单查询)无需握手,减少延迟。
  • 实时性好:无需重传(重传会增加延迟),适合实时音视频;无拥塞控制,应用可按固定速率发送数据(如直播需稳定码率)。

(3)安全性补充:SSL(安全套接层)

TCP 和 UDP 均为明文传输(如 Telnet 登录密码、Email 用户名口令可被抓包获取),需通过 SSL 增强安全性。

  • 层级:运行在应用层,基于 TCP 服务(SSL over TCP),本质是应用层的安全库。
  • 核心功能:提供私密性(数据加密)、完整性(防止数据篡改)、可认证性(验证服务器 / 客户端身份)。
  • 典型应用:HTTPS(Web 应用通过 SSL 加密,地址栏显示 “https://”),如淘宝、天猫登录 / 支付时,用户名和口令通过 SSL 加密传输。

2.1.5关键概念总结

  1. 进程标识:IP + 传输层协议(TCP/UDP)+ 端口号,唯一定位分布式进程。
  2. Socket:TCP 用四元组(会话关系)、UDP 用二元组(本地端节点),是应用层与传输层的 “交互门户”,本地整数标识。
  3. 应用架构:C/S(集中资源,可扩展性差)、P2P(分布式资源,可扩展性好)、混合(结合二者优势)。
  4. 传输层选择:可靠选 TCP,实时选 UDP,安全需叠加 SSL。
  5. 应用创新:端系统部署、核心无介入,是互联网应用快速迭代和国内创新领先的关键。

2.2Web and HTTP

2.2.1Web 核心术语

(1)Web 对象(Object)

  • 课件定义:Web 页由多个对象组成,包括 HTML 文件、JPEG 图像、Java 小程序、声音剪辑等;Web 页含 “基本 HTML 文件”,该文件包含其他对象的引用(链接),每个对象通过 URL 唯一标识。
  • 补充:
    • Web 对象并非 “包含” 其他对象,而是通过 “链接” 指向对象的 URL。例如访问中科大主页时,首先获取的 “基本 HTML 文件” 仅含网页框架(文字格式、布局),图像(如 “孺子牛” 雕塑、东校门照片)需通过 HTML 中的图像链接单独请求。
    • 浏览器解析基本 HTML 后,会识别所有对象链接,逐个通过 URL 请求对应对象,最终在客户端渲染出完整网页。互联网中 Web 对象构成 “网状信息空间”(类似蜘蛛网),目前网页数量达数千亿,需搜索引擎(百度、谷歌)通过 URL 建索引,优先推送热度高、关联度高的内容。

(2)统一资源定位符(URL)

  • 课件格式Prot://user:psw@www.someSchool.edu/someDept/pic.gif:port,含协议名、用户 / 口令、主机名、路径名、端口号 5 个部分。
  • 逐段解析:
    • 协议名(Prot):指定访问协议(如 HTTP、FTP),决定默认端口(HTTP 默认 TCP 80,FTP 默认 TCP 21)。例如访问www.ustc.edu.cn无需加:80,浏览器自动使用 HTTP 默认端口;
    • 用户 / 口令(user:psw):仅用于需身份验证的场景(如企业内部系统),公开网站(中科大、天猫)支持 “匿名访问”,此部分可省略;
    • 主机名 + 路径名 + 文件名:主机名(如www.someSchool.edu)指定对象所在服务器域名,路径名(/someDept)和文件名(pic.gif)指定对象在服务器的存储位置;
    • 端口号(port):非特殊情况可省略,默认使用协议对应的知名端口(如 HTTP 80、FTP 21)。

2.2.2HTTP 协议概况

(1)HTTP 核心定义

  • 定义:

    • 超文本传输协议(HTTP)是 Web 的应用层协议,基于客户 - 服务器(C/S)模式:客户端为请求 / 显示 Web 对象的浏览器(如 Firefox、Safari),服务器为响应请求的 Web 服务器(如 Apache、IIS);
    • 版本规范:HTTP 1.0(RFC 1945)、HTTP 1.1(RFC 2068);
    • 运行在 TCP 之上:客户端发起 TCP 连接(默认端口 80),服务器接受连接后交换 HTTP 报文,交互完成后关闭连接(非持久)或保留连接(持久)。
  • “超文本” 含义:非线性格式,通过链接实现对象间的任意指向(即 Web 对象的网状关联),与 “线性文本(如 Word 文档)” 区别;

  • 互操作性原理:不同厂商的浏览器(Chrome、Edge)与服务器(Apache、Windows IIS)可通信,核心是均遵守 HTTP 协议的报文格式、交互规则(如 ASCII 编码、请求 - 响应时序);

  • 服务器 Socket 机制:

    1. 服务器创建 “欢迎 Socket(Welcome Socket)”,绑定 80 端口并阻塞式等待客户端连接;
    2. 收到连接请求后,创建 “连接 Socket(Connection Socket)” 用于专属通信(欢迎 Socket 继续等待其他客户端);
    3. 若同时有 3 个浏览器请求,服务器生成 3 个连接 Socket,实现多客户端并发访问。

(2)HTTP 无状态特性

  • 课件定义:服务器不维护客户端的任何状态信息,每个请求独立 —— 服务器无法识别 “同一客户端是否曾访问”“之前请求过什么资源”。
  • 无状态优势:
    1. 服务器无需维护历史状态(如客户端死机后的状态同步),逻辑简单;
    2. 相同硬件 / 软件资源可支持更多客户端(无状态服务器能同时响应数千请求,有状态服务器仅支持数百个);
  • 无状态局限:无法满足需 “用户状态跟踪” 的场景(如电子商务购物车、用户登录),需通过Cookies 机制弥补。

2.2.3HTTP 连接模式(持久 vs 非持久)

(1)非持久连接(HTTP 1.0 默认)

  • 核心定义:“最多只有一个对象在 TCP 连接上发送,下载多个对象需要多个 TCP 连接”。

  • 交互流程(以 “包含 1 个 HTML+10 个图像的 Web 页” 为例):

    1. 初始 HTML 文件的请求与传输

      • 建立 TCP 连接:

        • 客户端向服务器www.someSchool.edu的 80 端口(HTTP 默认端口)发起 TCP 连接请求;

        • 服务器在 80 端口守候连接,接受请求并告知客户端,TCP 连接建立。

      • 发送 HTTP 请求:客户端通过已建立的 TCP 连接,发送 HTTP 请求报文,请求目标对象someDepartment/home.index(即网页的 HTML 文件)。

      • 服务器响应:服务器接收到请求后,检索到对应的 HTML 对象,将其封装为 HTTP 响应报文,通过 TCP 连接发送给客户端。

      • 关闭 TCP 连接:服务器完成响应后,关闭当前 TCP 连接。

      • 客户端解析 HTML:客户端接收响应报文,显示 HTML 内容;同时解析 HTML,发现其中包含 10 个 JPEG 图像的引用链接。

    2. 10 个 JPEG 图像的请求与传输

      对 HTML 中引用的每个 JPEG 图像,重复执行上述步骤 1-5:

      • 为每个图像单独建立新的 TCP 连接(目标仍为服务器 80 端口);
      • 发送 HTTP 请求、接收图像响应、关闭连接;
      • 依次完成 10 个图像的请求与传输。
  • 非持久 HTTP 连接的核心特点

每个对象(包括初始 HTML、每个图像)都对应独立的 TCP 连接,即 “一个对象对应一次连接建立→请求→响应→连接关闭” 的完整流程,连接无法复用。

  • 响应时间模型:公式 “响应时间 = 2RTT + 传输时间”。
    • 1 个 RTT 用于 TCP 连接建立,1 个 RTT 用于 HTTP 请求 - 响应交互(请求报文小,传输时间忽略);
    • 传输时间:对象(如 100KB 图像)的传输耗时,取决于对象大小和链路带宽;
    • 非持久连接缺点:多对象下载需多次建立 TCP 连接,每个对象额外消耗 2RTT,操作系统需为每个连接分配资源,效率低。

(2)持久连接(HTTP 1.1 默认)

  • 课件核心定义:“多个对象可以在一个(客户端和服务器之间的)TCP 连接上传输”,分为 “非流水方式” 和 “流水方式”。

  • 老师讲解的交互流程(同上述 Web 页案例):

    1. 初始 TCP 连接建立与 HTML 文件的请求与传输

      • 建立 TCP 连接:
        • 客户端向服务器www.someSchool.edu的 80 端口(HTTP 默认端口)发起 TCP 连接请求;
        • 服务器在 80 端口维护 “欢迎 Socket”,接受连接后创建新的 “连接 Socket”(用于与该客户端专属通信),TCP 连接建立(仅需 1 次,后续复用)。
      • 发送 HTTP 请求:客户端通过已建立的 TCP 连接,发送 HTTP 请求报文,请求目标对象someDepartment/home.index(即网页的 HTML 文件)。
      • 服务器响应:服务器接收到请求后,检索到对应的 HTML 对象,将其封装为 HTTP 响应报文,通过同一 TCP 连接发送给客户端。
      • 连接不关闭:与非持久连接不同,服务器发送 HTML 响应后,TCP 连接保持开放状态,用于后续图像对象的传输。
      • 客户端解析 HTML:客户端接收响应报文,显示 HTML 内容;同时解析 HTML,发现其中包含 10 个 JPEG 图像的引用链接。
    2. 10 个 JPEG 图像的请求与传输(复用同一 TCP 连接)

      客户端解析出 10 个图像链接后,无需重新建立 TCP 连接,直接在已有的 TCP 连接上进行交互:

      • 发送图像请求:客户端采用 “流水方式”,无需等待前一个图像响应,立即连续向服务器发送 10 个 JPEG 图像的 HTTP 请求(请求报文体积小,传输时间可忽略);
      • 服务器依次响应:服务器按请求接收顺序,将 10 个 JPEG 图像分别封装为 HTTP 响应报文,通过同一 TCP 连接依次返回给客户端;
      • 连接仍可复用:所有图像传输完成后,TCP 连接仍保持开放(除非客户端 / 服务器显式设置Connection: close或触发空闲超时),若客户端后续需请求该服务器的其他对象,可继续复用此连接。
  • 两种持久连接方式:

    • 非流水方式(课件定义):“客户端只能在收到前一个响应后才能发出新的请求”,每个对象消耗 1 个 RTT;
    • 流水方式(课件定义,HTTP 1.1 默认):“客户端遇到一个引用对象就立即产生一个请求”,所有小对象仅需 1 个 RTT 即可完成传输,大幅减少延迟。
  • 持久连接优势:减少 TCP 连接建立次数,降低 RTT 消耗;避免操作系统频繁分配连接资源,提升效率。

2.2.4HTTP 报文格式

(1)HTTP 请求报文

  • 课件定义格式:ASCII 编码(人可阅读),由 “请求行、首部行、空行(表示报文结束前的分隔)、实体主体(可选)” 组成。
  • 各部分详解:
    • 请求行:格式为 “方法 URL HTTP 版本”,课件列出核心方法:
      • GET:从服务器获取对象(最常用),可通过 URL 参数传递数据(如http://www.baidu.com/s?wd=xx+yy&cl=3wdcl为参数,值分别为xx+yy3);
      • POST:向服务器提交数据(如表单输入),数据存于 “实体主体” 中,而非 URL(避免参数暴露);
      • HEAD:仅获取对象的首部(无实体主体),课件说明 “用于故障跟踪”,老师补充:搜索引擎爬虫常用此方法获取网页描述信息(如标题、修改时间)以建索引,无需下载完整网页;
      • PUT/DELETE(HTTP 1.1 新增):PUT 用于向服务器上传文件(如网站维护时更新 HTML),DELETE 用于删除服务器文件(需权限),老师说明 “仅网络管理员通过网站发布工具使用”。
    • 首部行:格式为 “首部字段名:值”,课件示例包括:
      • Host: www.someschool.edu:指定目标服务器域名(即使已建立 TCP 连接,仍需明确主机,支持一台服务器托管多个网站);
      • User-agent: Mozilla/4.0:标识客户端浏览器类型和版本(服务器可根据此返回适配的页面);
      • Connection: close:指定连接为非持久(即使 HTTP 1.1,也可强制关闭连接);
      • Accept-language: fr:指定客户端接受的语言(如法语)。
    • 实体主体:仅 POST、PUT 方法使用,存储提交的数据(如表单的用户名、密码)。

(2)HTTP 响应报文

  • 定义格式:ASCII 编码,由 “状态行、首部行、空行、实体主体” 组成。

  • 状态行:格式为 “HTTP 版本 状态码 状态信息”,课件列出核心状态码:

    • 200 OK:请求成功,实体主体包含请求对象(如 HTML 文件、图像);
    • 301 Moved Permanently:请求对象永久迁移,新 URL 在Location首部行中,浏览器自动跳转;
    • 400 Bad Request:服务器无法解析请求(如请求报文格式错误);
    • 404 Not Found:请求对象在服务器中不存在(常见 “页面丢失” 场景);
    • 505 HTTP Version Not Supported:服务器不支持请求的 HTTP 版本(如不支持 HTTP 2.0)。
  • 首部行:格式为 “首部字段名:值”,课件示例包括:

    • Server: Apache/1.3.0 (Unix):标识服务器类型和运行环境;

    • Content-Length: 6821:指定实体主体的字节数(关键!因 TCP 是 “字节流服务”,不维护报文边界,客户端需通过此值确定对象结束位置);

    • Date: Thu, 06 Aug 1998 12:00:15 GMT:服务器生成响应的时间;

    • Content-Type: text/html:指定实体主体的 MIME 类型(如 text/html 表示 HTML 文件,image/jpeg 表示 JPEG 图像);

    • Last-Modified: Mon, 22 Jun 1998 ...:指定对象最后修改时间(用于后续 “条件 GET” 验证版本一致性)。

    • 实体主体:存储请求的对象(如 HTML 文件内容、图像二进制数据)。

2.2.5HTTP 无状态的补充:Cookies 机制

(1)Cookies 的组成与工作流程

  • 定义:维护 “用户 - 服务器状态” 的机制,含 4 个部分:
    1. HTTP 响应报文中的Set-Cookie首部行;
    2. HTTP 请求报文中的Cookie首部行;
    3. 客户端本地的 Cookie 文件(浏览器管理,如 Windows 对应目录下的文本文件);
    4. 服务器端的后端数据库(存储 Cookie 关联的用户状态)。
  • 举例(苏珊访问亚马逊):
    1. 苏珊首次访问亚马逊,HTTP 请求无 Cookie;
    2. 亚马逊服务器生成唯一 Cookie ID(如 1687),通过响应报文Set-Cookie: 1687告知客户端,同时在数据库创建该 ID 的记录;
    3. 苏珊的浏览器将 Cookie ID 存到本地文件;
    4. 后续访问时,浏览器通过请求报文Cookie: 1687携带 ID,服务器关联她的状态(登录信息、购物车商品、历史订单)。

(2)Cookies 的功能与隐私风险

  • 核心功能:
    • 用户验证:无需重复登录(如淘宝登录后,下次访问自动识别);
    • 购物车:记录用户添加的商品(如京东 “加入购物车” 后,关闭浏览器仍保留);
    • 个性化推荐:基于历史访问记录推荐商品(如亚马逊 “猜你喜欢”);
    • 用户状态维护:如记录论坛编辑帖子的草稿进度。
  • 隐私风险(重点强调):
    • 服务器可通过 Cookie 追踪用户长期访问行为(如浏览记录、消费偏好),甚至关联多个网站的 Cookie 数据,挖掘用户隐私(如身份、消费能力);
    • 第三方广告公司可能通过 Cookie 收集用户数据,定向推送广告(如用户聊过 “空调” 后,多个 APP 推送空调广告),存在信息泄露风险。

2.2.6Web 缓存(代理服务器)

(1)Web 缓存的定义与作用

  • 课件定义:“缓存既是客户端又是服务器”,由 ISP(大学、公司、居民区 ISP)部署,目标是 “不访问原始服务器(Origin Server)就满足客户请求”—— 客户端请求先发送到缓存,缓存有对象则直接返回,无则向原始服务器请求并本地存储。
  • 核心优势:
    • 减少客户端响应时间:缓存位于本地(如大学局域网内),访问延迟远低于远程原始服务器;
    • 减少网络流量与服务器负载:缓存命中的请求无需通过接入链路和互联网,降低网络拥塞,同时减少原始服务器的请求量(符合 “二八规律”:80% 用户访问 20% 热点内容,缓存可高效命中)。

(2)缓存实例计算

  • 场景假设:

    • 平均对象大小 = 100KB;
    • 机构内浏览器对原始服务器的平均请求率 = 15 请求 / 秒(总下载速率 = 1.5Mbps);
    • 机构到原始服务器的 Internet 延迟 = 2 秒;
    • 接入链路带宽 = 1.544Mbps。
  • 无缓存的问题:

    • 接入链路流量强度 = 1.5Mbps/1.544Mbps≈0.99(接近 1),排队延迟达 “分钟级”;
    • 总响应时间 = LAN 延迟(毫秒级)+ 接入链路延迟(分钟级)+Internet 延迟(2 秒)≈分钟级,用户无法忍受(早期 Web 被戏称为 “world wide wait”,浏览器显示 “咖啡加载动画” 提示等待)。
  • 解决方案对比:

    解决方案 课件 + 老师计算结果 成本与效果
    土豪方案:扩容接入链路至 154Mbps 接入链路流量强度 = 1.5Mbps/154Mbps≈0.01,排队延迟可忽略,总响应时间≈2 秒 + LAN 延迟 成本极高(每月带宽费用增 100 倍),效果一般;
    优化方案:部署本地缓存(命中率 0.4) 接入链路流量强度 = 0.6×1.5Mbps/1.544Mbps≈0.58,总响应时间≈1.2 秒 一次性投入(缓存服务器廉价),效果优于扩容(延迟更低),网络管理员推荐;

2.2.7条件 GET 方法

  • 课件定义:目标是 “若缓存中的对象拷贝为最新,则不传输对象”,核心是请求报文中的If-Modified-Since首部行。
  • 讲解完整流程:
    1. 缓存首次获取对象时,存储对象的 “最后修改时间”(从原始服务器响应的Last-Modified首部获取);
    2. 客户端请求该对象时,缓存向原始服务器发送请求,首部行加If-Modified-Since: [对象最后修改时间]
    3. 原始服务器判断:
      • 若对象在该时间后未修改:返回响应HTTP/1.0 304 Not Modified(无实体主体,仅首部行),缓存直接返回本地对象;
      • 若对象已修改:返回响应HTTP/1.0 200 OK(含最新对象),缓存更新本地对象并返回给客户端。
  • 老师强调作用:解决 “缓存对象与服务器对象版本不一致” 问题,同时减少冗余数据传输(304 响应仅含首部,比 200 响应节省 90% 流量)。

2.3 FTP(文件传输协议)

2.3.1FTP 协议的基本定位与应用场景

(1)核心内容

  • FTP(File Transfer Protocol)是用于向远程主机传输文件或从远程主机接收文件的应用层协议,遵循客户 - 服务器(C/S)模式,对应的 RFC 文档为 RFC 959。
  • FTP 服务器默认守候在TCP 21 号端口,客户端发起传输请求,服务器作为远程主机提供文件存储与访问能力。

(2)补充讲解

  • 应用场景演变:FTP 是早期互联网文件共享的核心方式,如中国科学技术大学等机构曾长期维护 FTP 服务器,用于共享学术资源、软件等;用户通过 FTP 客户端上载文件到服务器,再由其他用户下载,还可在 BBS 等平台同步服务器文件目录信息。
  • 现代替代方案:当前 FTP 使用频率下降,被迅雷、百度云盘、群文件分发等更便捷的工具替代,但 FTP 的 “客户端 - 服务器文件传输” 核心逻辑仍是基础网络应用设计的重要参考。

2.3.2FTP 的客户 - 服务器体系结构

(1)核心内容

FTP 的应用组件分为客户端与服务器两部分,具体结构如下:

组件类型 包含模块 功能描述
FTP 客户端 用户接口、FTP 客户端软件、本地文件系统 发起文件传输请求(上载 / 下载),提供用户操作界面,管理本地文件的读取与存储
FTP 服务器 FTP 服务器软件、远程文件系统 守候在 TCP 21 号端口,接收客户端连接,管理远程文件系统的目录与文件,响应客户端的传输请求

(2)补充讲解

  • 客户端角色:是 “发起传输的一方”,需主动与服务器建立连接,通过用户接口输入用户名、口令完成认证,再执行目录浏览、文件传输等操作。
  • 服务器角色:是 “提供文件服务的远程主机”,需提前运行服务器软件并守候在 21 号端口,维护远程文件系统的权限(如哪些用户可访问哪些目录),并响应客户端的命令。

2.3.3FTP 的核心机制:控制连接与数据连接分离

(1)核心内容

  • FTP 使用两个独立的 TCP 连接完成文件传输:
    • 控制连接(Control Connection):服务器端端口为 21,用于传输用户认证信息(用户名、口令)、客户端命令(如目录列表、文件传输指令)及服务器响应(状态码、操作结果)。
    • 数据连接(Data Connection):服务器端端口为 20,用于传输实际的文件数据(上载 / 下载的文件内容)或目录列表数据。
  • 控制连接为 “带外(out of band)” 传输,数据连接为 “带内传输”,二者独立工作,确保命令交互与数据传输不冲突。

(2)补充讲解(连接建立与工作流程)

①控制连接的建立与作用
  1. 连接发起:FTP 服务器先运行,持续守候在 TCP 21 号端口;客户端主动向服务器的 21 号端口发起 TCP 连接请求,建立控制连接。
  2. 用户认证:在控制连接上,客户端以明文形式发送用户名(USER 命令)和口令(PASS 命令),服务器验证通过后允许后续操作(注:明文传输存在安全隐患,抓包工具可直接获取认证信息)。
  3. 命令交互:认证通过后,客户端通过控制连接向服务器发送操作命令(如查看目录、上传 / 下载文件),服务器通过控制连接返回响应(状态码 + 解释),整个命令交互过程仅在控制连接上进行。
②数据连接的建立与作用
  1. 连接发起:当客户端发送文件传输命令(如下载文件的 RETR 命令、上传文件的 STOR 命令)后,服务器主动向客户端的 20 号端口发起 TCP 连接请求,建立数据连接(与多数 C/S 应用中 “客户端主动建连接” 的逻辑不同,是 FTP 的独特设计)。
  2. 数据传输:仅在数据连接上传输实际数据 —— 下载时,服务器将文件数据通过数据连接发送给客户端;上传时,客户端将本地文件数据通过数据连接发送给服务器;传输完成后,服务器关闭当前数据连接(若需传输新文件,需重新建立数据连接)。
③关键特点
  • 控制连接全程保持打开(直至客户端主动断开),用于持续的命令交互;数据连接 “按需建立、用完关闭”,每个文件传输(或目录列表获取)对应一个独立的数据连接。
  • “带外传输” 的含义:控制命令(认证、操作指令)与数据(文件内容)在不同连接上传输,控制命令不占用数据连接带宽,避免命令交互阻塞数据传输。

(4)FTP 的命令与响应机制

①课件核心内容
  • 命令(控制连接上传输,ASCII 文本格式):
    • USER username:向服务器提交用户名,用于身份认证。
    • PASS password:向服务器提交口令,完成身份认证。
    • LIST:请求服务器返回当前目录的文件列表(列表数据通过数据连接传输)。
    • RETR filename:从服务器的当前目录 “下载” 指定文件(客户端视角),文件数据通过数据连接传输。
    • STOR filename:向服务器的当前目录 “上载” 指定文件(客户端视角),文件数据通过数据连接传输。
  • 响应(控制连接上传输,ASCII 文本格式,含状态码 + 解释):
    • 331 Username OK, password required:用户名验证通过,需进一步提交口令。
    • 125 Data connection already open; transfer starting:数据连接已建立,即将开始数据传输。
    • 425 Can’t open data connection:无法建立数据连接(如客户端 20 号端口被占用)。
    • 452 Error writing file:文件写入失败(如服务器磁盘空间不足)。
②补充讲解
  • 命令与响应的交互逻辑:客户端发送一条命令后,需等待服务器返回响应(状态码),确认命令执行结果后再发送下一条命令,避免命令冲突。
  • 上载 / 下载的定义(客户端视角):
    • 上载(STOR 命令):客户端将本地文件系统的文件发送到服务器的远程文件系统。
    • 下载(RETR 命令):客户端从服务器的远程文件系统获取文件,保存到本地文件系统。
    • (避免混淆:若以服务器为视角,“上载” 对应服务器 “接收”,“下载” 对应服务器 “发送”,但行业默认以客户端视角定义)。

2.3.5FTP 的状态特性

(1)核心内容

FTP 服务器会维护用户的状态信息,包括:用户当前所在的目录(如 “/home/user/docs”)、用户账户的权限(如是否允许上载)、与该用户对应的控制连接状态。

(2)补充讲解

  • 有状态的必要性:FTP 需记录用户当前目录(否则客户端执行 “LIST” 命令时,服务器无法确定返回哪个目录的列表),且需关联用户账户与控制连接(确保同一控制连接下的命令来自已认证用户)。
  • 与 HTTP 的对比:HTTP 协议初始设计为 “无状态”(服务器不维护客户端状态,每次请求独立),后续需通过 Cookie 补充状态管理;而 FTP 天然为 “有状态”,服务器需持续维护客户端的会话信息,直至客户端断开控制连接。

2.3.6FTP 与 HTTP 的关键差异(结合前文内容总结)

对比维度 FTP HTTP(参考 2.2 节内容)
连接数量 两个独立 TCP 连接(控制连接 21、数据连接 20) 单个 TCP 连接(非持久连接:一个连接传一个对象;持久连接:一个连接传多个对象)
传输内容分离 控制命令(带外,控制连接)、数据(带内,数据连接)分离 控制信息(请求行、首部行)与数据(响应体)在同一连接传输(带内)
状态特性 有状态(服务器维护用户当前目录、账户权限) 无状态(服务器不维护客户端状态,需 Cookie 补充)
核心用途 文件传输(上载 / 下载,需明确指定文件路径) Web 资源获取(HTML、图片等,通过 URL 定位资源)
认证方式 控制连接上明文传输用户名 + 口令 可选认证(如 Basic 认证,也可通过 Cookie、Token 认证,早期也存在明文风险)

2.3.7后续知识点预告

关于 “FTP 客户端与服务器如何通过 Socket API 建立 TCP 连接”(如服务器调用socket()bind()listen()accept()函数,客户端调用socket()connect()函数),将在本章 2.8 节(TCP 套接字编程)和 2.9 节(UDP 套接字编程)中详细讲解,当前只需理解 “通过 Socket API 按规则调用,即可建立 TCP 连接” 的核心逻辑,无需深入底层函数调用顺序。

2.4 Email(电子邮件)

2.4.1电子邮件的核心组成与基本流转逻辑

(1)课件核心要点

电子邮件系统包含 3 个主要组成部分:用户代理(User Agent)邮件服务器(Mail Server)简单邮件传输协议(SMTP);邮件服务器间通过 SMTP 通信,用户通过邮件访问协议(POP3/IMAP/HTTP)从服务器获取邮件。

(2)补充讲解

  1. 各组成部分的具体作用

    • 用户代理:是用户与电子邮件系统交互的 “客户端软件”,负责撰写、编辑、发送、接收和显示邮件,相当于 “电子邮件应用的代理”。

      举例:Outlook、Foxmail(常见桌面端);类比 Web 应用的用户代理是浏览器,FTP 应用的用户代理是 FTP 客户端软件,用户需通过该软件间接与服务器交互。

    • 邮件服务器:始终运行(守候在 TCP 25 端口,SMTP 默认端口),核心作用有二:

      ① 接收用户代理发送的邮件,存入 “输出报文队列”,按顺序转发至目标邮件服务器(避免 “发送速度>转发能力” 导致的拥堵,部分服务器会设置 5-10 分钟 “攒批发送”,减少频繁连接的负载);

      ② 接收其他邮件服务器发来的邮件,存入对应用户的 “邮箱(Mailbox)”(每个用户在服务器上有专属邮箱,用于暂存他人发送的邮件)。

    • 协议分工:

      • 「发送端」用SMTP(推模式):将邮件从用户代理→源邮件服务器、源邮件服务器→目标邮件服务器;
      • 「接收端」用POP3/IMAP/HTTP(拉模式):用户代理从目标邮件服务器的邮箱中拉取邮件,完成接收。
  2. 基本流转逻辑(“两推一拉”)

    以 “Alice(中科大邮箱)给 Bob(谷歌邮箱)发邮件” 为例:

    ① 推 1:Alice 通过 Outlook(用户代理),用 SMTP 将邮件推至中科大邮件服务器的 “输出队列”;

    ② 推 2:中科大邮件服务器(SMTP 客户端)主动连接谷歌邮件服务器(SMTP 服务器),用 SMTP 将邮件推至 Bob 的专属邮箱;

    ③ 拉:Bob 打开 Foxmail(用户代理),用 POP3/IMAP/HTTP 从谷歌邮件服务器的邮箱中拉取邮件,完成接收。

2.4.2简单邮件传输协议(SMTP,RFC 2821)

(1)核心要点

SMTP 使用 TCP 协议(端口 25),直接在发送方与接收方邮件服务器间传输;传输分 3 阶段(握手、传输报文、关闭);命令 / 响应为 ASCII 文本格式;要求报文(首部 + 主体)为 7 位 ASCII 码。

(2)补充讲解

  1. SMTP 的 “客户端 - 服务器” 角色动态性

    SMTP 的客户端 / 服务器角色并非固定:

    • 当 “用户代理→源邮件服务器” 传输时:用户代理是 SMTP 客户端,源邮件服务器是 SMTP 服务器;
    • 当 “源邮件服务器→目标邮件服务器” 传输时:源邮件服务器(如中科大邮件服务器)是 SMTP 客户端,目标邮件服务器(如谷歌邮件服务器)是 SMTP 服务器。
  2. 传输三阶段的具体交互(ASCII 明文,可通过 Telnet 模拟)

    以 “Alice 的邮件从源服务器→目标服务器” 为例,交互过程如下(红色为客户端命令,黑色为服务器响应):

    阶段 交互内容(示例)
    握手阶段 1. 服务器:220 hamburger.edu(TCP 连接就绪)
    2. 客户端:HELO crepes.fr(告知自身身份)
    3. 服务器:250 Hello crepes.fr, pleased to meet you(欢迎,握手成功)
    传输报文阶段 1. 客户端:MAIL FROM: alice@crepes.fr(指定发件人)
    2. 服务器:250 alice@crepes.fr... Sender ok(发件人验证通过)
    3. 客户端:RCPT TO: bob@hamburger.edu(指定收件人)
    4. 服务器:250 bob@hamburger.edu ... Recipient ok(收件人验证通过)
    5. 客户端:DATA(开始传输邮件内容)
    6. 服务器:354 Enter mail, end with "." on a line by itself(提示 “以单独一行的‘.’结束”)
    7. 客户端:Do you like ketchup?How about pickles?.(传输邮件正文,以 “.” 结束)
    8. 服务器:250 Message accepted for delivery(邮件接收成功)
    关闭阶段 1. 客户端:QUIT(请求关闭连接)
    2. 服务器:221 hamburger.edu closing connection(关闭连接)
  3. SMTP 的关键特性与局限性

    • 特性 1:持久连接:一次 TCP 连接可传输多个邮件(如中科大服务器向谷歌服务器发多个用户的邮件,无需频繁断连重连),提升传输效率;
    • 特性 2:推模式:与 HTTP 的 “拉模式”(客户端请求→服务器响应)不同,SMTP 主动将邮件 “推” 向目标服务器;
    • 特性 3:多对象封装:HTTP 一个响应报文仅含一个对象(如一个 HTML 文件),而 SMTP 一个报文可包含多个对象(如邮件正文 + 多张图片附件);
    • 局限性:仅支持 7 位 ASCII 码:无法直接传输中文、可执行文件(.exe)、图片(.jpg)等非 ASCII 内容,需通过 MIME 扩展解决;
    • 安全隐患:明文传输:命令、响应(含发件人、用户名信息)均为明文,易被窃取或伪造(如伪造 MAIL FROM 字段发送虚假邮件),后续可通过 SSL/TLS 加密(如 SMTPS,端口 465)弥补。

2.4.3邮件报文格式与 MIME 扩展(多媒体邮件扩展)

(1)核心要点

  • RFC 822 定义文本报文格式:首部(Header)+ 空行 + 主体(Body)
  • MIME(RFC 2045、2056,多媒体邮件扩展):为解决非 ASCII 内容传输,在报文首部添加额外行,申明内容类型、编码方式。

(2)补充讲解

  1. RFC 822 文本报文格式细节

    • 首部:由多个 “字段名:值” 对组成,常见字段及作用:

      字段名 作用示例
      To 收件人邮箱(如 “To: bob@hamburger.edu”)
      From 发件人邮箱(如 “From: alice@crepes.fr”)
      Subject 邮件主题(标题,如 “Subject: Picture of yummy crepe”)
      CC 抄送:将邮件副本发送给其他接收者,所有收件人可见抄送对象(如抄送领导,同事可查看)
      BCC 暗抄送:将邮件副本发送给其他接收者,主收件人不可见暗抄送对象(隐私性更强)
    • 空行:严格分隔首部与主体,是报文格式的核心分隔标志(无空行则首部与主体会混淆);

    • 主体:邮件正文,原始仅支持 7 位 ASCII 字符(英文可正常传输,中文会乱码)。

  2. MIME 扩展的作用与原理

    • 核心问题:SMTP 仅支持 7 位 ASCII,非 ASCII 内容(如中文 “你好”、JPEG 图片二进制流)无法直接传输;

    • 解决思路:通过 MIME 字段声明编码规则,将非 ASCII 内容 “转换” 为 ASCII 格式传输,接收端再 “还原” 为原始内容;

    • 关键 MIME 字段(示例):

      From: alice@crepes.fr
      To: bob@hamburger.edu
      Subject: Picture of yummy crepe.
      MIME-Version: 1.0  # 声明MIME版本
      Content-Transfer-Encoding: base64  # 声明编码方式为Base64
      Content-Type: image/jpeg  # 声明内容类型为JPEG图片
      base64 encoded data .....  # Base64编码后的图片数据
      
    • Base64 编码原理:将非 ASCII 的二进制数据(如中文的 2 字节、图片的二进制流)按规则映射为 ASCII 字符集中的 64 种可打印字符(0-9、A-Z、a-z、+、/),传输后接收端通过反向映射还原原始数据(虽增加约 33% 的数据量,但解决了兼容性问题)。

2.4.4邮件访问协议(从邮件服务器获取邮件)

(1)核心要点

邮件访问协议用于用户代理从邮件服务器的 “用户邮箱” 中获取邮件,主要包括 3 类:

  • POP3(RFC 1939):邮局访问协议,简单的 “下载型” 协议;
  • IMAP(RFC 1730):Internet 邮件访问协议,复杂的 “管理型” 协议;
  • HTTP:用于 Web 邮件(如 Hotmail、Yahoo! Mail),借助 HTTP 的文件传输能力实现邮件收发。

(2)邮局访问协议(POP3,Port 110)

  • 核心定位:功能简洁的 “下载工具”,仅支持身份认证与邮件下载,适用于单设备(如个人 PC)使用场景。

  • 交互三阶段:

    1. 用户确认阶段(认证):

      • 客户端发送USER <用户名>(如 “user bob”),服务器返回+OK(用户名有效);
      • 客户端发送PASS <密码>(如 “pass hungry”),服务器返回+OK(认证成功)或-ERR(密码错误);
      • 安全问题:用户名、密码均为明文传输,需结合 SSL/TLS(如 POP3S,Port 995)加密。
    2. 事务处理阶段:

      • 常用命令:

        命令格式 作用示例
        LIST 请求邮件列表(如服务器返回 “1 498”“2 912”,表示 1 号邮件 498 字节、2 号 912 字节),以 “.” 结束
        RETR <邮件号> 下载指定邮件(如 “retr 1” 下载 1 号邮件),服务器返回邮件内容,以 “.” 结束
        DELE <邮件号> 标记指定邮件为删除(如 “dele 1”),断开连接后生效
      • 两种下载模式:

        模式 特点 优缺点
        下载并删除 下载后服务器删除该邮件 优点:不占用服务器空间;缺点:仅单设备可见,其他设备(如手机)无法获取
        下载并保留 下载后服务器保留该邮件 优点:多设备(平板、PC)可重复获取;缺点:长期占用服务器空间
    3. 关闭阶段:客户端发送QUIT,服务器返回+OK(关闭连接,标记删除的邮件生效)。

  • 关键特性:无状态协议。因 POP3 不支持远程目录维护(无法在服务器邮箱创建文件夹),服务器仅需记录 “用户是否认证”“用户邮箱” 等基础信息,无需跟踪邮箱内文件的操作状态(如邮件是否被移动)。

(3) Internet 邮件访问协议(IMAP,Port 143)

  • 核心定位:功能复杂的 “邮件管理工具”,支持下载与远程目录维护,适用于多设备同步(如手机、平板、PC)场景。
  • 核心特性(对比 POP3):
    1. 远程目录维护:用户可在客户端远程管理服务器邮箱的文件夹(如创建 “工作邮件”“个人邮件” 文件夹,将邮件在文件夹间移动、标记 “已读 / 未读”);
    2. 有状态协议:服务器需维护客户端的操作状态(如当前访问的文件夹、邮件的读取状态),确保多设备同步(如手机标记 “已读”,电脑打开时也显示 “已读”);
    3. 精细带宽控制:支持仅下载邮件首部(主题、发件人),再决定是否下载正文与附件(如手机流量环境下,先看主题再选择性下载),节省带宽。

(4)HTTP 协议(Web 邮件场景)

  • 核心定位:借助 HTTP 的 “上载 / 下载” 能力,实现无客户端的邮件访问(如网页版 QQ 邮箱、Yahoo! Mail)。
  • 原理:
    • 发送邮件:用户在浏览器(HTTP 客户端)填写邮件内容,通过 HTTP POST 将内容上传至 Web 邮件服务器,服务器再通过 SMTP 将邮件转发至目标服务器;
    • 接收邮件:用户通过浏览器发送 HTTP GET 请求,Web 邮件服务器从用户邮箱读取邮件,封装为 HTTP 响应返回给浏览器;
  • 优势:无需安装专用客户端(如 Outlook),跨设备、跨系统(Windows、macOS、手机浏览器)均可访问,兼容性极强。

2.5.5电子邮件协议流转全景总结

链路类型 涉及协议 方向 核心动作
发送链路(推) SMTP(Port 25) 用户代理→源邮件服务器 上传邮件至源服务器队列
发送链路(推) SMTP(Port 25) 源邮件服务器→目标邮件服务器 转发邮件至目标服务器用户邮箱
接收链路(拉) POP3/IMAP/HTTP 用户代理→目标邮件服务器 从用户邮箱拉取邮件至本地
扩展支持 MIME 全链路 解决非 ASCII 内容传输
安全增强 SSL/TLS 全链路 加密 SMTP/POP3/IMAP 的明文数据

2.5 DNS(Domain Name System)

2.5.1DNS 的必要性 —— 为什么需要 DNS

  1. IP 地址的局限性:IP 地址(如 IPv4 的 32 位、IPv6 的 128 位数字)是主机 / 路由器的唯一标识,但存在 “难记忆、无实际意义” 的问题,不符合人类使用习惯(例如用户更易记www.ustc.edu.cn,而非202.38.64.1)。
  2. 核心需求:实现 “有意义的字符串(域名)” 到 “IP 地址” 的转换,衔接人类认知习惯与网络底层的 IP 寻址需求 —— 用户输入域名后,需通过 DNS 将其转换为 IP 地址,才能让应用(如浏览器、邮件客户端)与目标服务器建立连接。

2.5.2DNS 的历史 —— 从集中式到分布式的演进

  1. ARPANET 时期的集中式方案

    • 早期 ARPANET 采用 “平面命名”(主机名无层次,如 “alice”“bob”),通过一台集中维护站管理Hosts.txt文件,记录所有主机名与 IP 的映射关系;

    • 每台主机需定时从维护站下载Hosts.txt更新本地映射。

  2. 集中式方案的缺陷

    • 重名问题:主机数量激增后,平面命名易出现全球重名,难以分配唯一标识;

    • 管理难题:Hosts.txt文件体积膨胀,更新、发布、查找效率极低;

    • 可靠性差:集中维护站宕机则全网无法解析。

  3. 演进方向:为解决集中式缺陷,DNS 采用 “层次化命名 + 分布式解析” 的设计,替代传统集中式方案。

2.5.3DNS 的总体思路与核心目标

  1. 总体思路

    • 命名机制:分层的、基于域的树状命名结构,避免重名;

    • 解析机制:通过若干分布式数据库(名字服务器)协同完成 “域名→IP” 转换;

    • 传输依赖:运行在 UDP 之上,使用 53 号知名端口(无需 TCP 握手,降低解析延迟,契合 “轻量、快速” 需求);

    • 复杂性定位:核心功能在网络边缘(端系统的应用层)实现,而非核心网络,降低核心网络负担。

  2. 核心目标

    • 基础目标:实现 “主机名→IP 地址” 的高效、可靠转换;

    • 扩展目标:

      • 主机别名转换(Host aliasing):将易记的 “别名” 转换为服务器的 “规范名”(如www.ibm.com(别名)→servereast.backup2.ibm.com(规范名));

      • 邮件服务器别名转换(Mail server aliasing):将邮件地址中的域名(如user@ustc.edu.cn)转换为邮件服务器的规范名及 IP;

      • 负载均衡(Load Distribution):为同一域名(如www.taobao.com)分配多台服务器 IP,根据用户位置、服务器负载动态选择,平衡压力。

2.5.4DNS 系统需解决的三大核心问题

(1)问题 1:如何命名设备 —— 层次化名字空间(The DNS Name Space)

  1. 解决的核心痛点:平面命名易重名,无法满足海量设备(百亿 / 千亿级)的唯一标识需求。

  2. 解决方案:层次树状命名结构

    • 结构层级(从顶层到底层):

      1. 根(Root):全球共 13 个根名字服务器(分布于北美、欧洲、日本等,中国大陆暂无),避免单根宕机导致全网解析失效;

      2. 顶级域(Top-Level Domains, TLD):分两类:

        • 通用顶级域(Generic TLD):如.com(商业)、.edu(教育)、.gov(政府)、.net(网络服务)、.org(非营利组织);

        • 国家 / 地区顶级域(Country-Code TLD):如.cn(中国)、.us(美国)、.jp(日本)、.uk(英国);

      3. 子域(Subdomains):顶级域下可划分二级域(如.edu.cn(中国教育网)、.com.cn(中国商业)),二级域可进一步划分三级域(如ustc.edu.cn(中国科学技术大学)),以此类推;

      4. 主机(Host):树状结构的 “树叶”,每个主机属于某一子域(如www.ustc.edu.cn中,www是主机名,对应科大的 Web 服务器)。

    • 域名规则

      • 域名格式:从 “底层(主机 / 子域)” 向 “顶层(根)” 遍历,各层级用 “.” 分隔(如主机域名www.auto.ustc.edu.cn,子域域名auto.ustc.edu.cn);

      • 域的管理:子域需经上级域同意才能创建(如创建auto.ustc.edu.cn,需ustc.edu.cn域管理者授权);

      • 域与物理网络无关:域是 “逻辑划分”,同一域的主机可分布在不同物理网络(如科大子域的主机可在合肥、北京、苏州等地),同一物理网络的主机也可属于不同域。

(2)问题 2:如何完成 “名字→IP” 转换 —— 分布式解析机制

  1. 集中式解析的缺陷:若用单台名字服务器维护全球所有域名 - IP 映射,会面临 “单点故障(服务器宕机则全网失效)、通信容量不足(查询请求过载)、维护复杂(增删域名需频繁修改单库)” 的问题。

  2. 解决方案:分布式解析(区域划分 + 名字服务器协同)

    • 区域(Zone)划分:

      • 将 DNS 层次化名字空间拆分为 “互不相交的区域”,每个区域是树状结构的一部分(如ustc.edu.cn可作为一个区域,包含其下所有子域和主机);

      • 每个区域部署 “权威名字服务器”(Authoritative Name Server),维护该区域内域名 - IP 映射的 “权威记录”(信息最准确,由区域管理者维护,不可随意篡改)。

    • 名字服务器的类型与角色:

      • 根名字服务器:全球 13 个,负责指向各顶级域的权威服务器(仅存储 “顶级域→顶级域权威服务器” 的映射,不存储具体主机的映射);

      • 顶级域(TLD)服务器:负责指向二级域的权威服务器(如.edu.cn的 TLD 服务器存储 “ustc.edu.cn→ustc.edu.cn权威服务器” 的映射);

      • 权威名字服务器:负责本区域内所有域名的 “域名→IP” 映射(如ustc.edu.cn的权威服务器存储www.ustc.edu.cn、mail.ustc.edu.cn等主机的 IP);

      • 本地名字服务器(Local Name Server):

        • 非层次化结构的 “代理服务器”,由用户设备通过 DHCP 自动配置或手工设置(如家庭网络的本地服务器通常是路由器 IP,企业 / 学校通常有专用本地服务器);

        • 用户发起 DNS 查询时,先发送到本地名字服务器,本地服务器优先查询自身缓存,缓存无结果则逐层向根、TLD、权威服务器查询。

    • 解析流程(以 “主机 cis.poly.edu 查询 gaia.cs.umass.edu 的 IP” 为例):

      • 两种查询方式:

        类型 定义 流程(以本地服务器为核心)
        递归查询 本地服务器接收用户查询后,全程代为向根、TLD、权威服务器查询,最终将结果返回用户 用户→本地服务器(请求)→本地服务器→根→TLD→权威服务器(逐层查询)→权威服务器→TLD→根→本地服务器→用户(返回结果)
        迭代查询 本地服务器向某一级服务器查询时,仅获取 “下一级服务器地址”,需自行继续查询 用户→本地服务器(请求)→本地服务器→根(根返回 TLD 地址)→本地服务器→TLD(TLD 返回权威服务器地址)→本地服务器→权威服务器(获取 IP)→本地服务器→用户
      • 关键依赖:上层域需维护两条核心记录,确保解析可向下追溯:

        • NS记录:格式(子域名称,子域权威服务器名称,NS,TTL),如(ustc.edu.cn,dns.ustc.edu.cn,NS,86400);

        • A记录:格式(权威服务器名称,权威服务器 IP,A,TTL),如(dns.ustc.edu.cn,202.38.64.5,A,86400)。

    • 性能优化:缓存机制

      • 原理:非权威服务器(如本地服务器、TLD 服务器)查询到域名 - IP 映射后,会将该记录缓存,默认TTL(生存时间)为 2 天(86400 秒 ×2);

      • 作用:

        • 提升效率:后续相同域名查询可直接从缓存获取,无需逐层查询;

        • 保证一致性:TTL过期后,缓存记录自动删除,需重新查询权威服务器,避免目标服务器 IP 变更导致缓存失效。

(3)问题 3:如何维护 DNS 系统 —— 域与记录的增删改查

  1. 核心维护对象:资源记录(Resource Record, RR)——DNS 分布式数据库的基本单元,所有域名 - IP 映射均以 RR 形式存储。

    • RR 格式:(domain_name, ttl, type, class, value)

      • domain_name:域名(如www.ustc.edu.cn、ustc.edu.cn);

      • ttl:生存时间(单位:秒),决定记录在缓存中的保留时长;

      • class:类别,Internet 环境下固定为IN(Internet);

      • type:记录类型(核心类型如下);

      • value:记录值(随type变化)。

    • 核心 RR 类型:

      类型 作用 示例(domain_name, ttl, type, class, value)
      A 主机名→IP 地址(仅 IPv4) (www.ustc.edu.cn,86400,A,IN,202.38.64.1)
      NS 域→该域的权威服务器名称 (ustc.edu.cn,86400,NS,IN,dns.ustc.edu.cn)
      CNAME 别名→规范名(主机别名转换) (www.ibm.com,86400,CNAME,IN,servereast.backup2.ibm.com)
      MX 域名→邮件服务器名称(邮件别名转换) (ustc.edu.cn,86400,MX,IN,mail.ustc.edu.cn)
  2. 新增一个域的流程(以 “在.com 域中创建networkutopia.com” 为例)

    • 步骤 1:向.com域的注册机构(如 Network Solutions)提交申请,提供networkutopia.com的权威服务器信息(包括权威服务器名称,如dns1.networkutopia.com;权威服务器 IP,如212.212.212.1);

    • 步骤 2:注册机构在.com的 TLD 服务器中添加两条 RR 记录:

      • NS 记录:(networkutopia.com,dns1.networkutopia.com,NS,86400);

      • A 记录:(dns1.networkutopia.com,212.212.212.1,A,86400);

    • 步骤 3:在networkutopia.com的权威服务器中添加内部服务的 RR 记录:

      • Web 服务器:(www.networkutopia.com,86400,A,IN,212.212.212.2);

      • 邮件服务器:(networkutopia.com,86400,MX,IN,mail.networkutopia.com)、(mail.networkutopia.com,86400,A,IN,212.212.212.3);

    • 步骤 4:等待全球 DNS 服务器缓存更新,新增域即可被全网解析。

2.5.5DNS 协议与报文格式

  1. 协议特点:DNS 查询报文与响应报文格式完全相同,仅通过 “标志位” 区分查询 / 响应。
  2. 报文结构(从首部到数据区)
字段 长度(字节) 作用
标识符(Identification) 2 唯一标识一次查询 / 响应,确保客户端能匹配请求与响应
标志位(Flags) 2 包含 “查询 / 响应”“递归请求 / 可用”“权威响应” 等标识(如0x0100表示响应、权威)
问题数(# Questions) 2 表示 “问题区” 包含的查询条目数量(通常为 1)
回答数(# Answers) 2 表示 “回答区” 包含的 RR 记录数量(查询成功则≥1,失败则为 0)
权威数(# Authority RRs) 2 表示 “权威区” 包含的权威服务器 RR 数量
附加数(# Additional RRs) 2 表示 “附加区” 包含的额外 RR 数量(如权威服务器的 A 记录,避免二次查询)
问题区(Questions) 可变 存储查询的域名和类型(如查询www.ustc.edu.cn的 A 记录)
回答区(Answers) 可变 存储查询结果(如www.ustc.edu.cn对应的 A 记录)
权威区(Authority) 可变 存储权威服务器的 RR 记录(如ustc.edu.cn的 NS 记录)
附加区(Additional) 可变 存储权威服务器的 A 记录(如dns.ustc.edu.cn的 A 记录)

2.5.6DNS 的安全性与健壮性

  1. 常见攻击类型及防护

    • DDoS 攻击(分布式拒绝服务):

      • 攻击目标:根名字服务器、TLD 服务器;

      • 攻击方式:发送海量 Ping 请求或 DNS 查询,占用服务器带宽和算力;

      • 防护措施:

        • 根服务器:部署流量过滤器(防火墙),过滤异常请求;

        • 本地服务器:缓存 TLD 服务器 IP,无需频繁查询根,降低根服务器负载;

      • 效果:根服务器从未被成功攻击瘫痪,TLD 服务器攻击影响有限(依赖缓存)。

    • 重定向攻击:

      • 攻击方式:

        • 中间人攻击:截获用户 DNS 查询,伪造错误 IP(如将www.bank.com指向钓鱼网站 IP);

        • DNS 中毒:向名字服务器发送伪造的 RR 记录,使其缓存错误映射;

      • 防护难点:需分布式截获和伪造,技术门槛高,实际成功案例少。

    • 利用 DNS 的 DDoS 放大攻击:

      • 攻击方式:伪造目标 IP 发送 DNS 查询(查询报文小),服务器返回大量 RR 记录(响应报文大),利用 “响应> 查询” 的流量差攻击目标;
      • 效果:放大倍数有限(通常 10-100 倍),且易被运营商检测,影响较小。
  2. 总体健壮性:DNS 通过 “多根冗余、分布式解析、缓存优化、流量防护”,成为 Internet 中可靠性最高的应用层服务之一。

2.5.7DNS 核心知识点总结

  1. 本质:应用层基础性服务,为其他应用(Web、FTP、Email)提供 “域名→IP” 转换支撑;

  2. 核心设计:层次化名字空间(解决命名)+ 分布式解析(解决转换)+ 资源记录(解决维护);

  3. 关键特性

    • 复杂性在边缘(端系统应用层),核心网络无 DNS 功能;

    • 依赖 UDP 53 端口,轻量快速;

    • 缓存优化性能,TTL 保证一致性;

    • 支持别名转换、负载均衡等扩展功能;

  4. 核心价值:连接人类 “易记域名” 与网络 “IP 寻址”,是 Internet 正常运行的基石。

2.6 P2P 应用

2.6.1纯 P2P 架构的定义与核心特点(对应课件 “纯 P2P 架构” 示意图)

(1)架构定义

  • 无(或极少)一直运行的中心服务器
  • 任意端系统(Peer 节点)可直接通信;
  • 每个 Peer 节点既是客户端也是服务器:在某会话中请求其他 Peer 资源时为客户端,在另一会话中为其他 Peer 提供资源时为服务器;
  • 节点特性:间歇性连接、IP 地址可能动态变化,整体架构难以集中管理;
  • 典型例子:Gnutella 、迅雷。

(2)核心优势

①极强的可扩展性
  • 随 Peer 节点数量增加,请求资源的节点与提供服务的节点同步增加(新节点既消耗资源也贡献资源),系统可轻松扩展到数百万甚至上千万用户级;
  • 对比 C/S 模式:C/S 因依赖中心服务器,用户量激增时服务器会成为瓶颈,难以支撑大规模用户。
②高可靠性
  • 无单点故障风险:业务由成千上万个 Peer 节点共同提供,单个节点宕机不会导致整个系统瘫痪;
  • 流量分布式:避免 C/S 模式中 “服务器宕机则全业务中断” 的问题(如 Skype、微信语音通话,即使部分节点下线,其他节点仍可通信)。
③低成本
  • 无需购买 / 维护昂贵的中心服务器及大带宽网络,成本分散到每个 Peer 节点(用户仅承担自身设备成本);
  • 对比 C/S 模式:C/S 需承担服务器硬件、软件许可证、带宽租赁等巨额运营成本(如视频点播 C/S 服务器,每月需向 ISP 支付高额流量费)。
④应用场景(老师补充实例)
  • 文件分发:BitTorrent(BT)、迅雷;
  • 流媒体:KanKan(国内方案,首次进入国外顶级教材);
  • 实时通信:VOIP(Skype)、微信 / QQ / 钉钉语音 / 视频通话(基于 P2P 优化,效果优于早期 Skype)。

2.6.2文件分发时间对比:C/S 模式 vs P2P 模式

(1)前提定义

  • 文件大小:F
  • 服务器上载带宽:Us
  • Peer 节点:第i个 Peer 的上载带宽Ui、下载带宽Di,客户端总数N
  • 客户端最小下载带宽:dmin(所有 Peer 中下载最慢的节点带宽)。

(2)C/S 模式文件分发时间

①时间下限公式

\(D_{C/S} \ge \max \left\{ \frac{NF}{U_s}, \frac{F}{d_{min}} \right\}\)

②公式含义
  • NF/Us:服务器需向N个客户端各上载 1 份文件,总上载量NF,受服务器带宽Us限制的时间;
  • dmin:每个客户端需下载 1 份文件,最慢客户端(dmin)的下载时间(决定所有客户端的 “最慢完成时间”)。
③瓶颈分析
  • N 较小时(如 8 个客户端):服务器带宽Us富裕(如Us=10Ui),瓶颈是dmin(客户端下载能力不足),下载时间较短;
  • N 极大时(如 100 万客户端):服务器需上载 100 万份文件,NF/Us成为瓶颈,时间随N 线性增加(例:8 个客户端 1 秒,100 万客户端需 100 万秒,约 11.5 天,完全不可忍受);
  • 本质:C/S 模式中客户端上载能力被浪费,所有负载集中于服务器。

(3)P2P 模式文件分发时间

①时间下限公式

\(D_{P2P} \ge \max \{ \frac{F}{U_s}, \frac{F}{d_{min}}, \frac{NF}{u_s + \sum u_i} \}\)

②公式含义
  • \(\frac{F}{U_s}\):服务器仅需上载 1 份文件(文件首次进入网络),是服务器侧的最小时间;
  • \(\frac{F}{d_{min}}\):与 C/S 一致,最慢客户端的下载时间;
  • $ \frac{NF}{u_s + \sum u_i} $:总下载量NF由 “服务器上载带宽Us+ 所有 Peer 上载带宽总和∑ui” 共同承担,体现 P2P“人人为我,我为人人” 的协作特性。
③优势分析(老师结合曲线)
  • N 极大时\(\sum u_i\)N增加而增大,分母\(u_s + \sum u_i\)显著提升,时间增加平缓(非线线性)
  • 对比曲线:
    • C/S 曲线:随N(0-35)线性上升,N=35 时时间约 3.5 小时;
    • P2P 曲线:随N缓慢上升,N=35 时时间约 1 小时,优势随N增大更明显;
  • 本质:P2P 将 “服务器单点负载” 转化为 “全网 Peer 协作负载”,可扩展性远优于 C/S。

2.6.3P2P 文件分发实例:BitTorrent(BT)

(1)核心概念

  • 洪流(Torrent):一组交换同一文件块的 Peer 节点集合(如 “计算机网络课件.torrent” 对应的所有下载 / 上传节点);
  • 跟踪服务器(Tracker):维护 Torrent 中活跃 Peer 列表,新 Peer 加入时需注册并获取 Peer 邻居列表;
  • 文件分块:将文件分割为 256KB 的独立块,Peer 通过交换块完成文件下载(避免单块过大导致的传输失败);
  • 扰动(Churn):Peer 动态上线 / 下线,部分 Peer 下载完整个文件后成为 “种子(Seed)”—— 可选择离开(利己)或留下(利他,继续为他人提供上载)。

(2)块请求策略

①bitmap 状态同步(对应课件 “bitmap 表格图”)
  • Peer 定期向邻居发送 “位图(bitmap)”:1 个比特标识 1 个块的持有状态(1 = 拥有,0 = 未拥有);
  • 作用:所有 Peer 通过 bitmap 实时知晓其他节点的块持有情况(如 Alice 的 bitmap 显示 “块 1-4 为 1,块 5-10 为 0”,则知道需向邻居请求块 5-10)。
②分阶段请求逻辑(老师结合 “吸血鬼” 实例)
  • 阶段 1:新 Peer(吸血鬼,无块):
    • 策略:随机请求块(饥不择食),先获取 4 块文件;
    • 原因:无块时无法为他人提供服务,随机请求可快速获得 “服务资本”;
  • 阶段 2:拥有 4 块后:
    • 策略:稀缺优先(请求 Torrent 中最少见的块);
    • 目的:避免稀缺块因 Peer 下线丢失(如某块仅 1 个 Peer 拥有,若该 Peer 下线则全网无法获取),保障集体利益;
    • 关联:稀缺块持有者会被更多 Peer 请求,间接提升自身被服务的优先级(利他即利己)。

(3)块发送策略:一报还一报(Tit-for-Tat)

①核心逻辑
  • Peer 仅向 “对自己提供最大带宽” 的 4 个邻居发送块(优化疏通,避免撒胡椒面式的带宽浪费);
  • 例:Alice 的邻居中,Bob 提供的下载带宽最大,则 Alice 优先向 Bob 发送块,其余邻居排队。
②动态调整机制(老师补充细节)
  • 每 10 秒:重新评估邻居带宽,更新 “top4 带宽提供者” 列表,优先服务新列表中的节点;
  • 每 30 秒:随机选择 1 个排队的邻居发送块(“优化疏通试探”);
    • 目的:避免错过高带宽潜力节点(如某排队节点实际带宽高但未被发现),提升全网整体传输速率;
  • 良性循环实例:
    1. Alice 随机向 Bob 发送块(优化疏通);
    2. Bob 成为 Alice 的 top4 带宽提供者,开始向 Alice 提供高带宽服务;
    3. Bob 成为 Alice 的 top4,Alice 继续优先服务 Bob,双方带宽持续提升。

2.6.4P2P 文件共享的核心问题与解决方案

P2P 文件共享需解决 2 大核心问题:资源定位(找到有目标文件的 Peer)、节点动态管理(处理 Peer 加入 / 退出),分三类解决方案:

(1)集中式目录

①工作原理
  1. Peer 注册:Peer 上线时向中心目录服务器上报 “自身 IP + 共享文件列表”;
  2. 资源查询:用户(如 Alice)输入关键字(如 “双截棍.MP3”),客户端向目录服务器请求;
  3. 文件传输:服务器返回有该文件的 Peer 列表(如 Bob),Alice 与 Bob 直接建立 HTTP 连接下载;
  4. 资源更新:Alice 下载完成后,向目录服务器注册该文件,成为新的服务节点(可向他人提供下载)。
②问题

  • 单点故障:目录服务器宕机则整个系统瘫痪;
  • 性能瓶颈:百万级 Peer 同时注册 / 查询时,服务器负载过高;
  • 版权风险:服务器易被定位,版权方可追责(Napster 因提供非授权 MP3 目录服务被关闭)。

(2)全分布式

①架构特点
  • 无中心服务器,Peer 通过 TCP 连接构成 “覆盖网(Overlay Network)”—— 逻辑网络,边为 Peer 间的协作关系(非物理链路,如 X 与 Y 有 TCP 连接则为邻居);
  • 协议开源:任何人可实现 Gnutella 客户端(类似 HTTP 与浏览器的关系),支持多版本互通。
②资源定位:查询洪泛(Flooding)
  1. Alice 向所有邻居发送查询请求(如 “双截棍.MP3”);
  2. 邻居收到请求后,除 “入站 Peer” 外,向所有其他邻居转发请求;
  3. 拥有文件的 Peer(如 Bob)沿原路径反向返回 “查询命中” 消息;
  4. Alice 收到消息后,直接与 Bob 建立连接下载。
③优化与问题(老师补充)
  • 查询优化:
    • TTL(生存时间):设置跳数限制(如 5-7 跳),避免查询无限循环;
    • 记录已转发查询:避免重复转发同一请求;
  • 问题:
    • 覆盖网构建复杂:新 Peer 需通过 “死党列表”(软件配置的常在线 Peer IP)发起 Ping,接收 Pong 后选 8-10 个邻居;
    • 查询效率低:泛洪导致网络负载大,实际使用中 “难以找到资源”,后期开源仍未普及。

(3)混合体

①架构设计
  • Peer 分两类:组长(Super Peer)组员(Ordinary Peer)
  • 层级关系:组员仅连接 1 个组长,组长间建立 TCP 连接构成骨干网;
  • 集中与分布式结合:组内集中(组长跟踪组员内容),组间分布式(组长间转发查询)。
②资源定位流程
  1. 组员向组长发送关键字查询(如 “周杰伦 - 青花瓷.MP3”);
  2. 组长匹配组员共享内容,若命中则返回 “文件哈希值 + Peer IP”;
  3. 若未命中,组长向其他组长转发查询,接收结果后汇总返回;
  4. 组员用 “文件哈希值”(唯一标识,避免同名文件混淆)向目标 Peer 请求下载。
③优化策
  • 请求排队:限制并行上载数量,保障每个传输的带宽;
  • 激励优先权:优先服务上载多的用户,鼓励利他行为;
  • 并行下载:从多 Peer 下载同一文件的不同块(利用 HTTP 字节范围首部),提升速率。

2.6.5结构化 P2P:分布式哈希表(DHT)

(1)核心思想

  • 哈希表实现资源与 Peer 的精准映射:Peer 和资源均分配唯一 ID(哈希值,如 16 字节),构建有序覆盖网(如环形),按规则路由查询;
  • 优势:解决非结构化 P2P 的查询效率低问题,是现代 P2P 的主流技术。

(2)关键机制

①ID 分配
  • Peer ID:由 Peer 的 IP 地址哈希生成(如 IP=1.1.1.1→哈希值 = 88);
  • 资源 ID:由文件内容哈希生成(如 “计算机网络课件.pdf”→哈希值 = 78)。
②环形覆盖网
  • Peer 按 ID 大小首尾相接构成环(如 ID=5→88→199→1011→5);
  • 存储规则:约定资源 ID 落在某 Peer ID 范围内则由该 Peer 管理(如 ID 6-88 的资源由 ID=88 的 Peer 管理,ID 89-199 的资源由 ID=199 的 Peer 管理)。
③查询流程
  • 用户查询资源 ID=78→按环形拓扑路由到 ID=88 的 Peer;
  • ID=88 的 Peer 返回资源所在的 Peer 列表(或直接提供资源);
  • 优势:精准路由(非泛洪),查询效率高,副本数量少(无需多节点备份)。

(3)应用与延伸

  • 现代 P2P 文件分发:迅雷、BitTorrent 改进版均基于 DHT;
  • 细节:DHT 的节点维护、路由优化等内容在 “高级计算机网络” 课程中深入,本章了解基本原理即可。

2.7 CDN

2.7.1背景:视频业务的重要性与核心挑战

  1. 视频是互联网杀手级应用

    • 定义:占网络流量比重大(七八成甚至更高)、最能吸引用户的业务。

    • 核心问题:如何向百万级并发用户提供高质量的视频播放服务?

      • 传统方案局限:早期服务器仅支持几十 / 几百并发,无法满足大规模需求。
  2. 两大核心挑战

    • 规模性挑战:需同时向海量用户提供 “流化服务”(实时播放)。

    • 异构客户端挑战:不同设备需求差异大(手机需低解析度,100 寸电视需高解析度(如 1080P)),且设备处理能力、网络带宽不一致。

2.7.2视频基础与压缩技术

  1. 视频的本质​

    • 视频是图像序列:依赖人眼 “视网膜滞留效应”(图像消失后滞留若干毫秒),帧率常见 24 帧 / 秒(电影)、60 帧 / 秒(游戏)。

    • 图像是像素的有序序列(Pixel 序列)。

  2. 视频必须压缩的原因与原理​

    • 原因:未压缩视频带宽极大(远超网络承载能力),需通过压缩降低码率。

    • 压缩基础:利用视频的 “空间冗余” 和 “时间冗余”

      • 空间冗余:同一帧内像素颜色相似(如蓝天区域),可描述 “某像素值持续多少个像素”。

      • 时间冗余:相邻帧中 “不动的部分多、动的部分少”(如人物说话时,背景不变),仅传输动的部分。

  3. 压缩标准与编码技术​

    • 码率类型

      • CBR(固定码率):压缩后码率固定(如 1M/2Mbps),适合带宽稳定场景。

      • VBR(可变码率):静态场景(如风景)码率低,动态场景(如打斗)码率高,更节省带宽。

    • 编码标准

      • 国际标准:H.264(AVC)、H.265(HEVC)。

      • 我国标准:IVS(高级视频编码),由科大吴峰校长助理(原院长)与导师高文院士联合提出,属国际标准。

    • (3)可伸缩编码(科大优势):由科大信息学院李卫平千人提出,可根据设备需求提供不同解析度(如手机 320×240、PC 1920×1080、电视 4K),适配异构客户端。

2.7.3视频点播的流化服务:Streaming 与 DASH

  1. 流化服务(Streaming) vs 下载播放(Download and Play)​

    • 下载播放:全量下载视频文件后再播放,等待时间长(如几 G 文件需几小时),体验差。

    • 流化服务:边下载边播放(客户端有缓冲区),大幅减少播放延迟(缓冲 7-8 秒即可开始,会员无广告更快),后续章节会讲 RTP 协议封装流化内容。

  2. DASH(动态自适应 HTTP 流化):解决异构与网络差异​

    • 定义:基于 HTTP 的动态自适应流化技术,适配不同客户端和网络状况。

    • 核心原理:

      • (1)视频预处理:将视频切成8-10 秒的块,每块生成 “低 / 中 / 高解析度”“不同编码” 的多个版本。
      • (2)Manifest 文件(告示文件):记录视频关键信息 —— 视频描述、块数量、每块持续时间、各版本块的 URL(存储位置)。
    • 客户端流程:

      1. 先下载 Manifest 文件并解析;

      2. 根据实时网络带宽(测带宽)、屏幕尺寸(设备需求)、缓冲区剩余量(避免卡顿),动态选择请求的块:

        • 带宽大 + 缓冲区满:请求高解析度块(提升体验);

        • 带宽小 + 缓冲区快空:请求低解析度块(避免 “努力缓冲中” 卡顿)。

    • DASH 的局限:若所有客户端都向 “少数源服务器” 请求块,会出现 3 个问题:

      • ① 客户端到服务器跳数多(网络质量不可控);
      • ② 网络重复流量多(多人下同一视频,浪费资源);
      • ③ 源服务器单点故障 / 性能瓶颈(并发过高崩溃)。

2.7.4CDN(内容分发网络):解决 DASH 局限,实现内容加速

  1. CDN 的定义与目标​

    • 定义:在应用层构建的 “内容分发网络”,通过分布式缓存节点,让用户 “靠近内容” 获取服务。

    • 目标:解决源服务器集中的问题(跳数多、重复流量、单点故障 / 拥塞),提升视频播放质量。

  2. CDN 的核心角色​

    • 新增角色:CDN 运营商(如美国阿卡米、中国蓝讯),ICP(内容提供商,如 CCTV、百度、网飞)需购买 CDN 服务。

    • 原有角色:终端用户、ISP、ICP(源服务器)。

  3. CDN 工作原理(三步)​

    1. 部署缓存节点:CDN 运营商在全球范围部署缓存节点(存储视频块)。
    2. 内容预先部署:ICP(如 CCTV)将视频内容通过专线,预先部署到 CDN 的缓存节点。
    3. 用户访问重定向:用户请求时,通过 “域名解析重定向”,引导至 “离用户最近、服务质量最好” 的缓存节点,由缓存节点提供流化服务(内容加速)。
  4. CDN 缓存节点部署策略(两种)​

策略名称 部署位置 优势 劣势 代表案例
In-to-Deep(深入群众) local ISP 内部(靠近用户) 跳数少、带宽大、服务质量高 节点数量多(数千个)、维护成本高 阿卡米
Bring Home(关键少数) 高层 ISP / 数据中心关键节点 节点数量少、维护成本低 到用户跳数稍多 中小型 CDN 运营商
  1. CDN 的实际应用实例​

实例 1:CCTV 春晚(高并发场景)

  • 问题:春晚点播量惊人,若全从 CCTV 源服务器请求,源服务器并发扛不住,且用户到源服务器跳数多(卡顿)。

  • 解决方案:CCTV 购买 “中国蓝讯” CDN 服务,将春晚视频通过专线部署到蓝讯全国缓存节点,用户由缓存节点服务 —— 跳数少、无卡顿,体验好。

实例 2:网飞(Netflix)

  • 网飞模式:

  1. 轻资产运营:认证服务器自维护(保障账号安全),视频制作、网页服务租用亚马逊云(降低成本);
  2. 内容分发:制作完的视频发布到 CDN 运营商(Level 3、阿卡米)的缓存节点;
  3. 用户流程:账号认证→浏览云网页→点视频链接→域名解析重定向到近的缓存节点→缓存节点提供 DASH 服务。

2.7.5CDN 的关键技术:域名解析重定向

  • 核心逻辑:通过域名解析,透明引导用户到近的缓存节点,用户无感知(不知道是源服务器还是缓存节点服务)。

  • 详细流程(以 “用户 Bob 访问 Net Cinema 视频” 为例):

  1. Bob 点视频链接(含域名),浏览器向 “local DNS” 请求解析该域名;
  2. local DNS 找到 “Net Cinema(ICP)的权威 DNS”,询问 IP;
  3. ICP 权威 DNS 不返回 IP,而是重定向:“请解析 CDN 运营商(King CDN)的域名”;
  4. local DNS 向 “King CDN 的权威 DNS” 请求解析;
  5. CDN 权威 DNS 根据 “Bob 的位置”“节点负载”,返回 “离 Bob 最近的缓存节点 IP”;
  6. Bob 向该缓存节点请求 DASH 服务(下 Manifest→选块→播放)。
  • 透明性:web 端、客户端无需任何修改,仅需在 ICP 权威 DNS(配置重定向)、CDN 权威 DNS(维护节点 IP 与距离)做配置。

2.7.6CDN 的特点与挑战

  1. CDN 的 OTT 特点(Over the Top)​

    • 含义:在应用层、网络边缘(缓存节点是主机)提供服务,不依赖网络核心设备,靠主机间配合实现加速(互联网 “Everything over IP” 架构的体现)。
  2. CDN 的三大挑战(研究生高级网络内容)​

    • 挑战 1:缓存节点选择 —— 多节点有同一内容时,选哪个节点(需测距离、带宽);

    • 挑战 2:节点切换 —— 当前缓存节点网络堵塞时,如何切换到其他节点;

    • 挑战 3:内容部署策略 ——ICP 的内容部署到哪些节点(需权衡成本:一次性投入、维护成本;地理位置:避免沙漠等交通不便处),需用数学、优化、运筹知识解决。

2.8 TCP 套接字编程

2.8.1TCP 套接字核心概念(对应课件图 3-137)

(1)套接字的本质与作用

  • 门户定位:套接字(Socket)是应用进程与传输层(TCP)之间的 “门户”—— 应用进程通过套接字发送 / 接收报文,无需关注传输层以下(IP、链路层等)的具体传输细节,仅需调用 Socket API 即可完成逻辑通信。
  • 类比理解:类似操作系统打开文件返回的 “文件句柄”,对套接字的读写操作,本质是对 “应用进程间 TCP 连接” 的操作。
  • TCP 服务特性:TCP 提供可靠的字节流服务(数据不丢失、不重复、不失序),但不保证报文界限(应用层需自行维护报文分隔,如 HTTP 的 CRLF.CRLF 标识报文结束),且是面向连接的服务(通信前需建立连接)。

(2)TCP 套接字的标识

  • 4 元组定义:TCP 套接字是 “(源 IP、源 TCP 端口、目标 IP、目标 TCP 端口)”4 元组的本地意义整数标识,唯一指定两个应用进程之间的 “会话关系”。
    • 例:客户端(IP:2.2.2.2,端口:777)与服务器(IP:1.1.1.1,端口:80)通信时,服务器的 TCP 套接字整数代表 “1.1.1.1:80 ↔ 2.2.2.2:777” 的连接,客户端的套接字代表反向关系。
  • 优势:应用进程无需在每次发送报文时重复指定 4 元组,仅通过该整数标识即可完成通信,简化编程与管理。

2.8.2C/S 模式下 TCP 套接字交互流程(对应课件图 3-138、3-140)

TCP 套接字编程基于 “客户 - 服务器(C/S)模式”,服务器必须先启动(否则客户端无连接对象),流程分为 “服务器端步骤” 和 “客户端步骤”,核心是 “欢迎套接字” 与 “连接套接字” 的分工。

(1)服务器端流程(核心:欢迎套接字 + 连接套接字)

步骤 操作(Socket API) 作用与细节 对应课件图
1 创建欢迎套接字 welcomeSocket = socket(PF_INET, SOCK_STREAM, 0)- 参数SOCK_STREAM指定为 TCP 套接字- 操作系统返回一个整数作为套接字标识(初始无实际意义) 3-138、3-140
2 绑定本地 IP 与端口 bind(welcomeSocket, &sad, sizeof(sad))- sadsockaddr_in结构体(存储本地 IP 和端口)- 端口需用htons()转换为网络字节序(解决大端 / 小端差异)- 服务器端口需固定(如 HTTP 的 80 端口),确保客户端可找到 3-138、3-141
3 监听连接请求 listen(welcomeSocket, 10)- 第二个参数 “10” 是等待队列长度(最多缓存 10 个未处理的连接请求)- 此时欢迎套接字进入 “监听状态”,准备接收客户端连接 3-140、3-146
4 接受连接(阻塞) connectionSocket = accept(welcomeSocket, &cad, &alen)- 阻塞等待:若无客户端连接,函数不返回,程序停滞- 接收到连接后,返回新的连接套接字connectionSocket)- cadsockaddr_in结构体,存储客户端的 IP 和端口- 关键区别:- 欢迎套接字(welcomeSocket):仅用于接受连接,长期存在- 连接套接字(connectionSocket):仅用于与当前客户端通信,通信结束后关闭 3-138、3-140
5 读写数据 read(connectionSocket, clientSentence, ...)``write(connectionSocket, capitalizedSentence, ...)- 通过连接套接字读取客户端发送的报文(如小写字符串)- 处理数据(如转为大写)后,通过同一套接字发送回客户端 3-140、3-146
6 关闭连接 close(connectionSocket)- 关闭当前客户端的连接套接字- 欢迎套接字仍保持监听,等待下一个客户端连接 3-140

(2)客户端流程(核心:隐式绑定 + 主动连接)

步骤 操作(Socket API) 作用与细节 对应课件图
1 创建客户端套接字 clientSocket = socket(PF_INET, SOCK_STREAM, 0)- 与服务器端socket函数参数一致,指定 TCP 类型- 操作系统返回整数标识,初始无绑定信息 3-140、3-143
2 隐式绑定本地 IP 与端口 无需调用bind函数!- 操作系统自动分配空闲的本地端口(如 777)和本地 IP- 客户端端口无需固定,服务器仅需知道自身端口即可 3-138、3-143
3 发起连接(阻塞) connect(clientSocket, &sad, sizeof(sad))- sadsockaddr_in结构体,存储服务器的 IP 和端口- 阻塞等待:直到 TCP 三次握手完成(服务器返回确认),函数才返回- 若连接失败(如服务器未启动),返回错误值 3-138、3-143
4 读写数据 write(clientSocket, Sentence, ...)``read(clientSocket, modifiedSentence, ...)- 向服务器发送数据(如用户输入的小写字符串)- 读取服务器返回的处理结果(如大写字符串) 3-140、3-144
5 关闭套接字 close(clientSocket)- 通信结束后,关闭客户端套接字,释放资源 3-140、3-144

2.8.3关键数据结构

TCP 套接字编程需借助两个核心结构体,用于存储 “IP + 端口” 和 “域名解析结果”,是 Socket API 的重要参数。

(1)sockaddr_in:存储 IP 与端口(端节点标识)

  • 结构定义:

    struct sockaddr_in 
    {short sin_family;        // 地址族:AF_INET(TCP/IP协议族)u_short sin_port;        // 端口号(需用htons()转为网络字节序)struct in_addr sin_addr; // 32位IP地址(如1.1.1.1)char sin_zero[8];        // 填充字段,用于内存对齐(无实际意义)
    };
    
  • 作用:

    • 服务器端:sad变量存储 “本地 IP + 固定端口”(如 1.1.1.1:80),用于bind绑定。
    • 客户端:sad变量存储 “服务器 IP + 服务器端口”(如 1.1.1.1:80),用于connect发起连接。
    • 服务器端accept时:cad变量存储 “客户端 IP + 客户端端口”(如 2.2.2.2:777),用于识别客户端。

(2)hostent:存储域名解析结果

  • 结构定义:

    struct hostent
    {char *h_name;        // 主机正式域名(如"www.ustc.edu.cn")char **h_aliases;    // 主机别名列表(如"ustc.cn")int h_addrtype;      // 地址类型:AF_INET(IPv4)int h_length;        // 地址长度:4字节(IPv4)char **h_addr_list;  // IP地址列表(字符串形式,如"1.1.1.1")
    #define h_addr h_addr_list[0] // 简化:取第一个IP地址
    };
    
  • 作用与使用:

    • 客户端需通过 “服务器域名”(如 "www.someschool.edu")获取服务器 IP,需调用gethostbyname函数:

      ptrh = gethostbyname(host); // host是客户端输入的服务器域名
      memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); // 将解析出的IP赋值给sad.sin_addr
      
    • 若域名解析成功,ptrh->h_addr存储服务器的 IPv4 地址;若失败,返回NULL

2.8.4TCP 套接字编程实例(C 语言)

以 “客户端发送小写字符串→服务器转为大写→客户端打印结果” 为例,展示核心代码与注释。

(1)客户端代码

/* client.c:TCP客户端,需输入两个参数:服务器域名、服务器端口 */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>void main(int argc, char *argv[]) 
{struct sockaddr_in sad;    // 存储服务器的IP和端口int clientSocket;          // 客户端套接字(整数标识)struct hostent *ptrh;      // 域名解析结果指针char Sentence[128];        // 存储用户输入的小写字符串char modifiedSentence[128];// 存储服务器返回的大写字符串char *host;                // 服务器域名int port;                  // 服务器端口// 1. 解析命令行参数(必须输入“服务器域名”和“端口”)host = argv[1];            // argv[1]:服务器域名(如"www.someschool.edu")port = atoi(argv[2]);      // argv[2]:服务器端口(如80),转为整数// 2. 创建TCP客户端套接字clientSocket = socket(PF_INET, SOCK_STREAM, 0); // SOCK_STREAM=TCPif (clientSocket < 0) { perror("socket error"); return; }// 3. 初始化sockaddr_in结构体(服务器地址信息)memset((char *)&sad, 0, sizeof(sad)); // 清空结构体,避免垃圾数据sad.sin_family = AF_INET;             // 协议族:TCP/IPsad.sin_port = htons((u_short)port);  // 端口转为网络字节序(大端)// 4. 域名解析:将服务器域名转为IP地址ptrh = gethostbyname(host);if (ptrh == NULL) { perror("gethostbyname error"); return; }memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); // 复制IP到sad// 5. 向服务器发起连接(阻塞至连接建立)if (connect(clientSocket, (struct sockaddr *)&sad, sizeof(sad)) < 0) {perror("connect error"); return;}// 6. 读取用户输入(标准输入:键盘)printf("Enter a lowercase sentence: ");gets(Sentence); // 读取用户输入的小写字符串// 7. 发送字符串到服务器write(clientSocket, Sentence, strlen(Sentence) + 1); // +1:包含字符串结束符'\0'// 8. 读取服务器返回的大写字符串read(clientSocket, modifiedSentence, sizeof(modifiedSentence));// 9. 打印结果并关闭套接字printf("FROM SERVER: %s\n", modifiedSentence);close(clientSocket);
}

(2)服务器端代码

/* server.c:TCP服务器,需输入一个参数:本地守候端口 */
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <ctype.h> // 用于toupper()函数(小写转大写)void main(int argc, char *argv[])
{struct sockaddr_in sad;     // 存储服务器的IP和端口struct sockaddr_in cad;     // 存储客户端的IP和端口int welcomeSocket;          // 欢迎套接字(接受连接)int connectionSocket;       // 连接套接字(与客户端通信)char clientSentence[128];   // 存储客户端发送的小写字符串char capitalizedSentence[128]; // 存储转换后的大写字符串int port;                   // 服务器本地守候端口socklen_t alen;             // 客户端地址结构体长度// 1. 解析命令行参数(必须输入“本地端口”)port = atoi(argv[1]);       // argv[1]:本地端口(如80)// 2. 创建TCP欢迎套接字welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);if (welcomeSocket < 0) { perror("socket error"); return; }// 3. 初始化sockaddr_in结构体(服务器地址信息)memset((char *)&sad, 0, sizeof(sad));sad.sin_family = AF_INET;              // 协议族:TCP/IPsad.sin_addr.s_addr = INADDR_ANY;      // 本地IP:绑定所有可用网卡(如1.1.1.1、192.168.1.1)sad.sin_port = htons((u_short)port);   // 端口转为网络字节序// 4. 绑定欢迎套接字与本地IP+端口if (bind(welcomeSocket, (struct sockaddr *)&sad, sizeof(sad)) < 0) {perror("bind error"); return;}// 5. 监听连接请求(等待队列长度10)listen(welcomeSocket, 10);alen = sizeof(cad); // 初始化客户端地址结构体长度// 6. 循环接受客户端连接(长期运行)while (1) {// 6.1 接受连接(阻塞,直到有客户端连接)connectionSocket = accept(welcomeSocket, (struct sockaddr *)&cad, &alen);if (connectionSocket < 0) { perror("accept error"); continue; }// 6.2 读取客户端发送的小写字符串read(connectionSocket, clientSentence, sizeof(clientSentence));// 6.3 小写转大写(核心业务逻辑)for (int i = 0; i < strlen(clientSentence); i++) {capitalizedSentence[i] = toupper(clientSentence[i]);}capitalizedSentence[strlen(clientSentence)] = '\0'; // 字符串结束符// 6.4 发送大写字符串给客户端write(connectionSocket, capitalizedSentence, strlen(capitalizedSentence) + 1);// 6.5 关闭当前客户端的连接套接字close(connectionSocket);}
}

2.8.5扩展:多进程处理多个客户端

(1)问题背景

上述服务器代码是 “单进程” 的:一次只能处理一个客户端(处理当前客户端时,accept阻塞,无法接受新连接)。若需同时服务多个客户端,需用多进程

(2)实现逻辑(对应课件无图,老师讲解补充)

  • 服务器accept获取connectionSocket后,调用fork()创建子进程
  • 子进程:负责与当前客户端通信(read/write/close(connectionSocket))。
  • 父进程:立即回到accept,继续阻塞等待新客户端连接(不处理通信)。

(3)核心代码片段

while (1) 
{connectionSocket = accept(welcomeSocket, &cad, &alen); // 接受连接if (fork() == 0) // 子进程(fork返回0){ read(connectionSocket, clientSentence, ...); // 子进程处理通信write(connectionSocket, capitalizedSentence, ...);close(connectionSocket);exit(0); // 子进程通信结束,退出} else // 父进程(fork返回子进程ID){ close(connectionSocket); // 父进程无需该套接字,关闭// 父进程直接回到accept,等待新连接}
}
  • 关键:父进程需关闭connectionSocket(避免资源泄漏),子进程通信结束后退出。
  • 优势:多个子进程可同时服务多个客户端,父进程仅负责 “接受连接”,提高并发能力。

2.8.6关键注意事项

  1. 网络字节序转换:端口号必须用htons()转换(主机字节序→网络字节序),否则不同架构(大端 / 小端)的设备会解析错误(如客户端发送端口 777,服务器可能解析为 30592)。
  2. 阻塞函数accept()connect()read()均为阻塞函数 —— 无数据 / 连接时,程序停滞,需等待事件发生(如客户端连接、数据到达)。
  3. 套接字区分:欢迎套接字(welcomeSocket)仅用于接受连接,不可用于通信;连接套接字(connectionSocket)仅用于单个客户端通信,通信结束必须关闭。
  4. 客户端隐式绑定:客户端无需bind,操作系统自动分配空闲端口,避免端口冲突(服务器必须bind固定端口,否则客户端无法找到)。
  5. 域名解析失败:若gethostbyname()返回NULL(如域名错误、网络不通),客户端需处理错误,不可继续connect

2.9 UDP 套接字编程

2.9.1UDP 套接字核心特性

(1)与 TCP 套接字的核心区别

  • 无连接 / 无握手:UDP 套接字在通信前无需建立连接(无 TCP 的三次握手),客户端创建套接字后可直接发送数据,服务器无需等待 “连接请求”。
  • 绑定范围不同:UDP 套接字仅与本地端节点(2 元组:本地 IP + 本地 UDP 端口) 绑定,不与对方的 IP / 端口绑定(TCP 套接字是 4 元组:源 IP + 源端口 + 目标 IP + 目标端口)。老师强调:“UDP socket 只是本地 IP 和端口的代表,发送时必须额外指明对方的 IP 和 UDP 端口,否则不知道发给谁”。
  • 无连接状态维护:UDP 套接字无 “连接状态”,每次发送数据都需明确指定目标端节点,接收数据时需通过引用参数获取发送方的端节点(以便回复)。

(2)UDP 套接字的标识

UDP 套接字在操作系统中以 “本地端节点” 为唯一标识,表格结构如下:

SOCKET(套接字描述符) IP(本地 IP 地址) Port(本地 UDP 端口号)
整数型标识(如 8888) 如 1.1.1.1 如 80(UDP 端口,与 TCP 端口分属不同空间)

注:老师特别说明 “UDP 端口和 TCP 端口是两个独立空间,比如 UDP 的 80 端口和 TCP 的 80 端口无关联,可同时被不同进程使用”。

2.9.2UDP 服务的本质

(1)UDP 向应用层提供的服务特性

  • 不可靠传输:数据可能丢失、乱序(无 TCP 的重传、排序机制),老师举例:“IP 数据报和 UDP 数据报都叫‘数据报(datagram)’,需结合上下文区分,但二者均为无连接、不可靠,UDP 的数据报是应用层与传输层间的 PDU”。
  • 无流量 / 拥塞控制:应用进程发送数据的速率由自身决定,UDP 不限制发送速率(与 TCP 的流量控制、拥塞控制不同)。
  • 数据报交付:UDP 以 “数据报” 为单位传输,每个数据报独立处理,应用层发送的每个报文会封装成一个 UDP 数据报(不会拆分或合并,除非超过 MTU)。

2.9.3UDP 客户端 - 服务器(C/S)交互流程

UDP C/S 通信无连接建立过程,流程如下(以 “客户端发送小写字符串,服务器返回大写字符串” 为例,老师逐步骤讲解):

(1)服务器端流程(对应课件 Server 交互步骤)

步骤 操作(对应课件代码逻辑) 老师补充说明
1 创建 UDP 套接字:serverSocket = socket(PF_INET, SOCK_DGRAM, 0) 指定 SOCK_DGRAM 标识为 UDP 套接字,返回整数型套接字描述符
2 绑定本地端节点:bind(serverSocket, (struct sockaddr *)&sad, sizeof(sad)) sadsockaddr_in 结构,存储本地 IP(如 INADDR_ANY,代表本机所有 IP)和 UDP 端口(如 80);UDP 服务器必须显式 bind,否则无法被客户端找到
3 循环接收客户端数据:recvfrom(serverSocket, clientSentence, sizeof(clientSentence), 0, (struct sockaddr *)&cad, &addr_len) - clientSentence 存储接收的字符串;- cad 是引用参数,通过它获取客户端的 sockaddr_in(IP + 端口),用于后续回复;- 若无数据,recvfrom 会阻塞,直到收到数据
4 处理数据:将 clientSentence 转换为大写(如 capitalizedSentence 此为应用层逻辑,与 UDP 协议无关,老师强调 “协议仅规范交互格式,内部数据处理由应用决定”
5 回复客户端:sendto(serverSocket, capitalizedSentence, strlen(capitalizedSentence)+1, (struct sockaddr *)&cad, &addr_len) 必须指定客户端的 cad(从 recvfrom 获取),否则无法定位客户端
6 持续循环:服务器无需关闭套接字,始终在 recvfrom 阻塞等待新请求 UDP 服务器无 welcome socket 与 connection socket 之分,仅一个 serverSocket 处理所有客户端请求(与 TCP 服务器不同)

(2)客户端流程(对应课件 Client 交互步骤)

步骤 操作(对应课件代码逻辑) 老师补充说明
1 创建 UDP 套接字:clientSocket = socket(PF_INET, SOCK_DGRAM, 0) 与服务器端创建方式一致,返回客户端套接字描述符
2 (可选)绑定本地端节点:bind(clientSocket, (struct sockaddr *)&sad, sizeof(sad)) 客户端可隐式绑定(操作系统自动分配 IP 和端口),老师建议 “若需固定客户端端口则显式 bind,否则无需手动操作”
3 初始化服务器端地址:sockaddr_in sad 赋值(sin_family=AF_INETsin_port=htons(服务器端口)sin_addr=服务器IP 服务器 IP 通过域名解析获取(gethostbyname(主机名) 得到 hostent 结构,再拷贝 IP 到 sin_addr
4 发送数据给服务器:sendto(clientSocket, Sentence, strlen(Sentence)+1, (struct sockaddr *)&sad, sizeof(sad)) 必须指定服务器的 sad(目标端节点),否则 UDP 不知道发送目标
5 接收服务器回复:recvfrom(clientSocket, modifiedSentence, sizeof(modifiedSentence), 0, (struct sockaddr *)&sad, &addr_len) 接收服务器返回的大写字符串,sad 可复用(此时存储服务器地址)
6 关闭套接字:close(clientSocket) 客户端通信结束后关闭套接字,释放资源

2.9.4UDP 编程关键数据结构(对应课件 sockaddr_in 与 hostent 结构)

(1)sockaddr_in 结构(对应课件 141 页,用于存储端节点信息

struct sockaddr_in {short sin_family;        // 地址族:必须为 AF_INET(Internet 协议族)u_short sin_port;        // UDP端口号:需转换为网络字节序(htons() 函数)struct in_addr sin_addr; // IP地址:存储32位IP地址(如INADDR_ANY代表本机所有IP)char sin_zero[8];        // 填充字段:用于与 sockaddr 结构对齐,需初始化为0
};

老师讲解:“sin_port 必须用 htons() 转换为网络字节序(大端序),避免主机字节序(小端序)与网络字节序不一致导致的端口错误;sin_addr 可通过 gethostbyname() 从域名获取 IP 地址”。

(2)hostent 结构(对应课件 142 页,用于域名解析)

struct hostent {char *h_name;        // 主机正式名称char **h_aliases;    // 主机别名列表int h_addrtype;      // 地址类型:AF_INET(IPv4)int h_length;        // 地址长度:IPv4为4字节char **h_addr_list;  // IP地址列表(网络字节序)
#define h_addr h_addr_list[0] // 宏定义:指向第一个IP地址(常用)
};

老师说明:“调用 struct hostent *ptrh = gethostbyname(主机名) 可通过域名(如 "www.ustc.edu.cn")获取 hostent 结构,再用 memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length) 将 IP 地址拷贝到 sockaddr_insin_addr 字段,实现域名到 IP 的转换”。

2.9.5UDP 编程代码示例解析(对应课件 C 客户端与服务器代码)

(1)C 客户端代码(对应课件 150-151 页)

void main(int argc, char *argv[]) {struct sockaddr_in sad;    // 存储服务器端节点信息int clientSocket;          // 客户端UDP套接字描述符struct hostent *ptrh;      // 域名解析结果指针char Sentence[128];        // 存储用户输入的字符串char modifiedSentence[128];// 存储服务器返回的大写字符串int port;                  // 服务器UDP端口号char *host;                // 服务器主机名(从参数获取)// 1. 从命令行参数获取服务器主机名和端口号host = argv[1];port = atoi(argv[2]);// 2. 创建UDP套接字clientSocket = socket(PF_INET, SOCK_DGRAM, 0);if (clientSocket < 0) { /* 错误处理(省略) */ }// 3. 初始化服务器端 sockaddr_in 结构memset((char *)&sad, 0, sizeof(sad)); // 清空结构sad.sin_family = AF_INET;             // Internet 协议族sad.sin_port = htons((u_short)port);  // 端口号转换为网络字节序// 4. 域名解析:将主机名转换为IP地址ptrh = gethostbyname(host);if (ptrh == NULL) { /* 错误处理(省略) */ }memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); // 拷贝IP地址// 5. 从标准输入获取用户输入gets(Sentence);// 6. 发送数据到服务器int addr_len = sizeof(struct sockaddr);sendto(clientSocket, Sentence, strlen(Sentence)+1, (struct sockaddr *)&sad, addr_len);// 7. 接收服务器回复recvfrom(clientSocket, modifiedSentence, sizeof(modifiedSentence), 0, (struct sockaddr *)&sad, &addr_len);// 8. 打印结果并关闭套接字printf("FROM SERVER: %s\n", modifiedSentence);close(clientSocket);
}

老师讲解重点:

  • 命令行参数 argv[1] 是服务器主机名(如 "1.1.1.1"),argv[2] 是服务器 UDP 端口(如 80);
  • sendto 的第 5 个参数是服务器的 sockaddr_in 指针,必须明确指定;
  • recvfrom 的第 6 个参数是引用参数,用于获取服务器的地址(此处可忽略,但需传入)。

(2) C 服务器代码(对应课件 152-153 页)

void main(int argc, char *argv[]) {struct sockaddr_in sad;     // 存储服务器端节点信息struct sockaddr_in cad;     // 存储客户端端节点信息(用于回复)int serverSocket;           // 服务器UDP套接字描述符char clientSentence[128];   // 存储客户端发送的字符串char capitalizedSentence[128]; // 存储转换后的大写字符串int port;                   // 服务器UDP端口号(从参数获取)int addr_len = sizeof(struct sockaddr); // 端节点结构长度// 1. 从命令行参数获取服务器端口号port = atoi(argv[1]);// 2. 创建UDP套接字serverSocket = socket(PF_INET, SOCK_DGRAM, 0);if (serverSocket < 0) { /* 错误处理(省略) */ }// 3. 初始化服务器端 sockaddr_in 结构memset((char *)&sad, 0, sizeof(sad)); // 清空结构sad.sin_family = AF_INET;             // Internet 协议族sad.sin_addr.s_addr = INADDR_ANY;     // 绑定本机所有IP地址sad.sin_port = htons((u_short)port);  // 端口号转换为网络字节序// 4. 绑定套接字与本地端节点if (bind(serverSocket, (struct sockaddr *)&sad, sizeof(sad)) < 0) {/* 错误处理(省略) */}// 5. 循环处理客户端请求while (1) {// 5.1 接收客户端数据(获取客户端地址 cad)recvfrom(serverSocket, clientSentence, sizeof(clientSentence), 0, (struct sockaddr *)&cad, &addr_len);// 5.2 处理数据:小写转大写(应用层逻辑)int i;for (i = 0; i < strlen(clientSentence); i++) {capitalizedSentence[i] = toupper(clientSentence[i]);}capitalizedSentence[i] = '\0'; // 字符串结束符// 5.3 回复客户端(使用 cad 定位客户端)sendto(serverSocket, capitalizedSentence, strlen(capitalizedSentence)+1, (struct sockaddr *)&cad, addr_len);}// 服务器通常不关闭套接字(循环永不退出)// close(serverSocket);
}

重点:

  • sad.sin_addr.s_addr = INADDR_ANY 表示绑定本机所有 IP 地址,客户端可通过任意一个本机 IP 访问服务器;
  • 循环 while(1) 使服务器持续运行,永不退出(除非手动终止);
  • recvfrom 的第 6 个参数 &cad 是关键:通过它获取客户端的地址,后续 sendto 才能精准回复该客户端;
  • 服务器无需区分不同客户端:所有客户端的请求都通过同一个 serverSocket 处理,通过 cad 区分不同客户端。

参考资料来源:中科大郑烇、杨坚全套《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》课程

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询