第2章應用層
應用層 概述
一、章節基本信息
- 章節主題:第 2 章 應用層
- 授課 / 改編方:中國科學技術大學 自動化系 鄭烇
- 參考教材:《Computer Networking: A Top-Down Approach》(第 7 版),Jim Kurose、Keith Ross 著,Addison-Wesley,April 2016
二、章節定位
本節課是 “自頂向下” 學習計算機網絡的開篇,聚焦網絡的最高層(應用層),本章包含原理、實例、編程三個核心部分,是應用層後續內容的總覽。
三、章節內容構成
- 原理部分:2.1 應用層協議原理
- 實例部分(互聯網流行應用 + 對應協議):
- 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(內容分發網絡)
- 編程部分: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 + 傳輸層協議 + 端口號
- 三要素組合:
- 主機 IP:定位進程所在的端系統(如 “哪台電腦”)。
- 傳輸層協議:區分進程使用 TCP 還是 UDP(二者端口號空間獨立)。
- 端口號:傳輸層引入的 16 位標識(0-65535),區分同一主機上的不同應用進程(如 HTTP 用 80、FTP 用 21,稱為 “知名端口”;客户端用動態端口)。
- 進程標識:用 “IP 地址 + 傳輸層協議(TCP/UDP) + 端口號” 唯一標識一個進程;一對進程的通信由兩個 “端節點(end point)” 構成(如 “源 IP: 源端口” 和 “目標 IP: 目標端口”)。
問題 2:如何使用傳輸層提供的服務(“如何把報文傳給對方”)
(1)核心需求
應用進程不能 “隔空發報文”,需通過層間接口(應用層與傳輸層的交互點)藉助傳輸層服務,本質是 “如何高效傳遞報文及必要控制信息”。
(2)層間接口的關鍵信息
應用層向傳輸層傳遞的信息需包含三類:
- SDU(服務數據單元):即要傳輸的報文本身(“貨物”)。
- 發送方標識:源進程的 “IP + 端口號”(便於接收方回覆,如 “發件人地址”)。
- 接收方標識:目標進程的 “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)應用協議的核心作用
定義 “不同端系統上的應用進程如何交換報文”,需包含四部分規則:
- 報文類型:如請求報文(客户端發給服務器)、響應報文(服務器返回客户端)。
- 語法:報文中的字段格式(如 HTTP 請求行的 “GET /xxx HTTP/1.1” 格式)。
- 語義:字段取值的含義(如 HTTP 響應碼 200 代表 “請求成功”,404 代表 “文件未找到”)。
- 時序與動作:進程何時發送報文、如何響應(如客户端先發請求,服務器接收後返回響應)。
(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 服務(面向連接、可靠傳輸)
- 核心特性:
- 可靠傳輸:發送端數據 100% 送達接收端(無丟失、無亂序、無重複)。
- 流量控制:防止發送方 “淹沒” 接收方(接收方處理慢時,通知發送方減速)。
- 擁塞控制:感知網絡擁堵(如丟包)時,主動降低發送速率,避免網絡癱瘓。
- 面向連接:通信前需建立連接(三次握手),連接持續期間會話關係穩定。
- 不提供的服務:無時間保證(無法承諾延遲)、無最小吞吐保證、無安全性(明文傳輸)。
- 適用場景:需高可靠性的應用(如 Web、Email、文件傳輸)。
②UDP 服務(無連接、不可靠傳輸)
- 核心特性:
- 不可靠傳輸:不保證數據送達,可能丟失、亂序。
- 無連接:通信前無需建立連接,每個報文獨立傳輸。
- 無額外控制:無流量控制、無擁塞控制,發送速率由應用決定。
- 不提供的服務:無可靠性、無流量 / 擁塞控制、無時間 / 帶寬保證、無連接建立。
- 適用場景:對實時性要求高、可容忍丟失的應用(如網絡電話、實時視頻、遊戲)。
③UDP 存在的必要性
- 區分進程:IP 僅能區分主機,UDP 通過端口號區分同一主機上的不同進程,實現 “進程到進程” 通信。
- 無需建立連接:事務性應用(如簡單查詢)無需握手,減少延遲。
- 實時性好:無需重傳(重傳會增加延遲),適合實時音視頻;無擁塞控制,應用可按固定速率發送數據(如直播需穩定碼率)。
(3)安全性補充:SSL(安全套接層)
TCP 和 UDP 均為明文傳輸(如 Telnet 登錄密碼、Email 用户名口令可被抓包獲取),需通過 SSL 增強安全性。
- 層級:運行在應用層,基於 TCP 服務(SSL over TCP),本質是應用層的安全庫。
- 核心功能:提供私密性(數據加密)、完整性(防止數據篡改)、可認證性(驗證服務器 / 客户端身份)。
- 典型應用:HTTPS(Web 應用通過 SSL 加密,地址欄顯示 “https://”),如淘寶、天貓登錄 / 支付時,用户名和口令通過 SSL 加密傳輸。
2.1.5關鍵概念總結
- 進程標識:IP + 傳輸層協議(TCP/UDP)+ 端口號,唯一定位分佈式進程。
- Socket:TCP 用四元組(會話關係)、UDP 用二元組(本地端節點),是應用層與傳輸層的 “交互門户”,本地整數標識。
- 應用架構:C/S(集中資源,可擴展性差)、P2P(分佈式資源,可擴展性好)、混合(結合二者優勢)。
- 傳輸層選擇:可靠選 TCP,實時選 UDP,安全需疊加 SSL。
- 應用創新:端系統部署、核心無介入,是互聯網應用快速迭代和國內創新領先的關鍵。
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)。
- 協議名(Prot):指定訪問協議(如 HTTP、FTP),決定默認端口(HTTP 默認 TCP 80,FTP 默認 TCP 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 機制:
- 服務器創建 “歡迎 Socket(Welcome Socket)”,綁定 80 端口並阻塞式等待客户端連接;
- 收到連接請求後,創建 “連接 Socket(Connection Socket)” 用於專屬通信(歡迎 Socket 繼續等待其他客户端);
- 若同時有 3 個瀏覽器請求,服務器生成 3 個連接 Socket,實現多客户端併發訪問。
(2)HTTP 無狀態特性
- 課件定義:服務器不維護客户端的任何狀態信息,每個請求獨立 —— 服務器無法識別 “同一客户端是否曾訪問”“之前請求過什麼資源”。
- 無狀態優勢:
- 服務器無需維護歷史狀態(如客户端死機後的狀態同步),邏輯簡單;
- 相同硬件 / 軟件資源可支持更多客户端(無狀態服務器能同時響應數千請求,有狀態服務器僅支持數百個);
- 無狀態侷限:無法滿足需 “用户狀態跟蹤” 的場景(如電子商務購物車、用户登錄),需通過Cookies 機制彌補。
2.2.3HTTP 連接模式(持久 vs 非持久)
(1)非持久連接(HTTP 1.0 默認)
-
核心定義:“最多隻有一個對象在 TCP 連接上發送,下載多個對象需要多個 TCP 連接”。
-
交互流程(以 “包含 1 個 HTML+10 個圖像的 Web 頁” 為例):
-
初始 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 圖像的引用鏈接。
-
-
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 頁案例):
-
初始 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 圖像的引用鏈接。
- 建立 TCP 連接:
-
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=3,wd和cl為參數,值分別為xx+yy和3); - POST:向服務器提交數據(如表單輸入),數據存於 “實體主體” 中,而非 URL(避免參數暴露);
- HEAD:僅獲取對象的首部(無實體主體),課件説明 “用於故障跟蹤”,老師補充:搜索引擎爬蟲常用此方法獲取網頁描述信息(如標題、修改時間)以建索引,無需下載完整網頁;
- PUT/DELETE(HTTP 1.1 新增):PUT 用於向服務器上傳文件(如網站維護時更新 HTML),DELETE 用於刪除服務器文件(需權限),老師説明 “僅網絡管理員通過網站發佈工具使用”。
- GET:從服務器獲取對象(最常用),可通過 URL 參數傳遞數據(如
- 首部行:格式為 “首部字段名:值”,課件示例包括:
Host: www.someschool.edu:指定目標服務器域名(即使已建立 TCP 連接,仍需明確主機,支持一台服務器託管多個網站);User-agent: Mozilla/4.0:標識客户端瀏覽器類型和版本(服務器可根據此返回適配的頁面);Connection: close:指定連接為非持久(即使 HTTP 1.1,也可強制關閉連接);Accept-language: fr:指定客户端接受的語言(如法語)。
- 實體主體:僅 POST、PUT 方法使用,存儲提交的數據(如表單的用户名、密碼)。
- 請求行:格式為 “方法 URL HTTP 版本”,課件列出核心方法:
(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 個部分:
- HTTP 響應報文中的
Set-Cookie首部行; - HTTP 請求報文中的
Cookie首部行; - 客户端本地的 Cookie 文件(瀏覽器管理,如 Windows 對應目錄下的文本文件);
- 服務器端的後端數據庫(存儲 Cookie 關聯的用户狀態)。
- HTTP 響應報文中的
- 舉例(蘇珊訪問亞馬遜):
- 蘇珊首次訪問亞馬遜,HTTP 請求無 Cookie;
- 亞馬遜服務器生成唯一 Cookie ID(如 1687),通過響應報文
Set-Cookie: 1687告知客户端,同時在數據庫創建該 ID 的記錄; - 蘇珊的瀏覽器將 Cookie ID 存到本地文件;
- 後續訪問時,瀏覽器通過請求報文
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首部行。 - 講解完整流程:
- 緩存首次獲取對象時,存儲對象的 “最後修改時間”(從原始服務器響應的
Last-Modified首部獲取); - 客户端請求該對象時,緩存向原始服務器發送請求,首部行加
If-Modified-Since: [對象最後修改時間]; - 原始服務器判斷:
- 若對象在該時間後未修改:返回響應
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)補充講解(連接建立與工作流程)
①控制連接的建立與作用
- 連接發起:FTP 服務器先運行,持續守候在 TCP 21 號端口;客户端主動向服務器的 21 號端口發起 TCP 連接請求,建立控制連接。
- 用户認證:在控制連接上,客户端以明文形式發送用户名(USER 命令)和口令(PASS 命令),服務器驗證通過後允許後續操作(注:明文傳輸存在安全隱患,抓包工具可直接獲取認證信息)。
- 命令交互:認證通過後,客户端通過控制連接向服務器發送操作命令(如查看目錄、上傳 / 下載文件),服務器通過控制連接返回響應(狀態碼 + 解釋),整個命令交互過程僅在控制連接上進行。
②數據連接的建立與作用
- 連接發起:當客户端發送文件傳輸命令(如下載文件的 RETR 命令、上傳文件的 STOR 命令)後,服務器主動向客户端的 20 號端口發起 TCP 連接請求,建立數據連接(與多數 C/S 應用中 “客户端主動建連接” 的邏輯不同,是 FTP 的獨特設計)。
- 數據傳輸:僅在數據連接上傳輸實際數據 —— 下載時,服務器將文件數據通過數據連接發送給客户端;上傳時,客户端將本地文件數據通過數據連接發送給服務器;傳輸完成後,服務器關閉當前數據連接(若需傳輸新文件,需重新建立數據連接)。
③關鍵特點
- 控制連接全程保持打開(直至客户端主動斷開),用於持續的命令交互;數據連接 “按需建立、用完關閉”,每個文件傳輸(或目錄列表獲取)對應一個獨立的數據連接。
- “帶外傳輸” 的含義:控制命令(認證、操作指令)與數據(文件內容)在不同連接上傳輸,控制命令不佔用數據連接帶寬,避免命令交互阻塞數據傳輸。
(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)補充講解
-
各組成部分的具體作用
-
用户代理:是用户與電子郵件系統交互的 “客户端軟件”,負責撰寫、編輯、發送、接收和顯示郵件,相當於 “電子郵件應用的代理”。
舉例:Outlook、Foxmail(常見桌面端);類比 Web 應用的用户代理是瀏覽器,FTP 應用的用户代理是 FTP 客户端軟件,用户需通過該軟件間接與服務器交互。
-
郵件服務器:始終運行(守候在 TCP 25 端口,SMTP 默認端口),核心作用有二:
① 接收用户代理髮送的郵件,存入 “輸出報文隊列”,按順序轉發至目標郵件服務器(避免 “發送速度>轉發能力” 導致的擁堵,部分服務器會設置 5-10 分鐘 “攢批發送”,減少頻繁連接的負載);
② 接收其他郵件服務器發來的郵件,存入對應用户的 “郵箱(Mailbox)”(每個用户在服務器上有專屬郵箱,用於暫存他人發送的郵件)。
-
協議分工:
- 「發送端」用SMTP(推模式):將郵件從用户代理→源郵件服務器、源郵件服務器→目標郵件服務器;
- 「接收端」用POP3/IMAP/HTTP(拉模式):用户代理從目標郵件服務器的郵箱中拉取郵件,完成接收。
-
-
基本流轉邏輯(“兩推一拉”)
以 “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)補充講解
-
SMTP 的 “客户端 - 服務器” 角色動態性
SMTP 的客户端 / 服務器角色並非固定:
- 當 “用户代理→源郵件服務器” 傳輸時:用户代理是 SMTP 客户端,源郵件服務器是 SMTP 服務器;
- 當 “源郵件服務器→目標郵件服務器” 傳輸時:源郵件服務器(如中科大郵件服務器)是 SMTP 客户端,目標郵件服務器(如谷歌郵件服務器)是 SMTP 服務器。
-
傳輸三階段的具體交互(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(關閉連接) -
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)補充講解
-
RFC 822 文本報文格式細節
-
首部:由多個 “字段名:值” 對組成,常見字段及作用:
字段名 作用示例 To 收件人郵箱(如 “To: bob@hamburger.edu”) From 發件人郵箱(如 “From: alice@crepes.fr”) Subject 郵件主題(標題,如 “Subject: Picture of yummy crepe”) CC 抄送:將郵件副本發送給其他接收者,所有收件人可見抄送對象(如抄送領導,同事可查看) BCC 暗抄送:將郵件副本發送給其他接收者,主收件人不可見暗抄送對象(隱私性更強) -
空行:嚴格分隔首部與主體,是報文格式的核心分隔標誌(無空行則首部與主體會混淆);
-
主體:郵件正文,原始僅支持 7 位 ASCII 字符(英文可正常傳輸,中文會亂碼)。
-
-
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)使用場景。
-
交互三階段:
-
用户確認階段(認證):
- 客户端發送
USER <用户名>(如 “user bob”),服務器返回+OK(用户名有效); - 客户端發送
PASS <密碼>(如 “pass hungry”),服務器返回+OK(認證成功)或-ERR(密碼錯誤); - 安全問題:用户名、密碼均為明文傳輸,需結合 SSL/TLS(如 POP3S,Port 995)加密。
- 客户端發送
-
事務處理階段:
-
常用命令:
命令格式 作用示例 LIST 請求郵件列表(如服務器返回 “1 498”“2 912”,表示 1 號郵件 498 字節、2 號 912 字節),以 “.” 結束 RETR <郵件號> 下載指定郵件(如 “retr 1” 下載 1 號郵件),服務器返回郵件內容,以 “.” 結束 DELE <郵件號> 標記指定郵件為刪除(如 “dele 1”),斷開連接後生效 -
兩種下載模式:
模式 特點 優缺點 下載並刪除 下載後服務器刪除該郵件 優點:不佔用服務器空間;缺點:僅單設備可見,其他設備(如手機)無法獲取 下載並保留 下載後服務器保留該郵件 優點:多設備(平板、PC)可重複獲取;缺點:長期佔用服務器空間
-
-
關閉階段:客户端發送
QUIT,服務器返回+OK(關閉連接,標記刪除的郵件生效)。
-
-
關鍵特性:無狀態協議。因 POP3 不支持遠程目錄維護(無法在服務器郵箱創建文件夾),服務器僅需記錄 “用户是否認證”“用户郵箱” 等基礎信息,無需跟蹤郵箱內文件的操作狀態(如郵件是否被移動)。
(3) Internet 郵件訪問協議(IMAP,Port 143)
- 核心定位:功能複雜的 “郵件管理工具”,支持下載與遠程目錄維護,適用於多設備同步(如手機、平板、PC)場景。
- 核心特性(對比 POP3):
- 遠程目錄維護:用户可在客户端遠程管理服務器郵箱的文件夾(如創建 “工作郵件”“個人郵件” 文件夾,將郵件在文件夾間移動、標記 “已讀 / 未讀”);
- 有狀態協議:服務器需維護客户端的操作狀態(如當前訪問的文件夾、郵件的讀取狀態),確保多設備同步(如手機標記 “已讀”,電腦打開時也顯示 “已讀”);
- 精細帶寬控制:支持僅下載郵件首部(主題、發件人),再決定是否下載正文與附件(如手機流量環境下,先看主題再選擇性下載),節省帶寬。
(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
- IP 地址的侷限性:IP 地址(如 IPv4 的 32 位、IPv6 的 128 位數字)是主機 / 路由器的唯一標識,但存在 “難記憶、無實際意義” 的問題,不符合人類使用習慣(例如用户更易記www.ustc.edu.cn,而非202.38.64.1)。
- 核心需求:實現 “有意義的字符串(域名)” 到 “IP 地址” 的轉換,銜接人類認知習慣與網絡底層的 IP 尋址需求 —— 用户輸入域名後,需通過 DNS 將其轉換為 IP 地址,才能讓應用(如瀏覽器、郵件客户端)與目標服務器建立連接。
2.5.2DNS 的歷史 —— 從集中式到分佈式的演進
-
ARPANET 時期的集中式方案:
-
早期 ARPANET 採用 “平面命名”(主機名無層次,如 “alice”“bob”),通過一台集中維護站管理Hosts.txt文件,記錄所有主機名與 IP 的映射關係;
-
每台主機需定時從維護站下載Hosts.txt更新本地映射。
-
-
集中式方案的缺陷:
-
重名問題:主機數量激增後,平面命名易出現全球重名,難以分配唯一標識;
-
管理難題:Hosts.txt文件體積膨脹,更新、發佈、查找效率極低;
-
可靠性差:集中維護站宕機則全網無法解析。
-
-
演進方向:為解決集中式缺陷,DNS 採用 “層次化命名 + 分佈式解析” 的設計,替代傳統集中式方案。
2.5.3DNS 的總體思路與核心目標
-
總體思路:
-
命名機制:分層的、基於域的樹狀命名結構,避免重名;
-
解析機制:通過若干分佈式數據庫(名字服務器)協同完成 “域名→IP” 轉換;
-
傳輸依賴:運行在 UDP 之上,使用 53 號知名端口(無需 TCP 握手,降低解析延遲,契合 “輕量、快速” 需求);
-
複雜性定位:核心功能在網絡邊緣(端系統的應用層)實現,而非核心網絡,降低核心網絡負擔。
-
-
核心目標:
-
基礎目標:實現 “主機名→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)
-
解決的核心痛點:平面命名易重名,無法滿足海量設備(百億 / 千億級)的唯一標識需求。
-
解決方案:層次樹狀命名結構:
-
結構層級(從頂層到底層):
-
根(Root):全球共 13 個根名字服務器(分佈於北美、歐洲、日本等,中國大陸暫無),避免單根宕機導致全網解析失效;
-
頂級域(Top-Level Domains, TLD):分兩類:
-
通用頂級域(Generic TLD):如.com(商業)、.edu(教育)、.gov(政府)、.net(網絡服務)、.org(非營利組織);
-
國家 / 地區頂級域(Country-Code TLD):如.cn(中國)、.us(美國)、.jp(日本)、.uk(英國);
-
-
子域(Subdomains):頂級域下可劃分二級域(如.edu.cn(中國教育網)、.com.cn(中國商業)),二級域可進一步劃分三級域(如ustc.edu.cn(中國科學技術大學)),以此類推;
-
主機(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” 轉換 —— 分佈式解析機制
-
集中式解析的缺陷:若用單台名字服務器維護全球所有域名 - IP 映射,會面臨 “單點故障(服務器宕機則全網失效)、通信容量不足(查詢請求過載)、維護複雜(增刪域名需頻繁修改單庫)” 的問題。
-
解決方案:分佈式解析(區域劃分 + 名字服務器協同)
-
區域(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 系統 —— 域與記錄的增刪改查
-
核心維護對象:資源記錄(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)
-
-
新增一個域的流程(以 “在.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 協議與報文格式
- 協議特點:DNS 查詢報文與響應報文格式完全相同,僅通過 “標誌位” 區分查詢 / 響應。
- 報文結構(從首部到數據區):
| 字段 | 長度(字節) | 作用 |
|---|---|---|
| 標識符(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 的安全性與健壯性
-
常見攻擊類型及防護:
-
DDoS 攻擊(分佈式拒絕服務):
-
攻擊目標:根名字服務器、TLD 服務器;
-
攻擊方式:發送海量 Ping 請求或 DNS 查詢,佔用服務器帶寬和算力;
-
防護措施:
-
根服務器:部署流量過濾器(防火牆),過濾異常請求;
-
本地服務器:緩存 TLD 服務器 IP,無需頻繁查詢根,降低根服務器負載;
-
-
效果:根服務器從未被成功攻擊癱瘓,TLD 服務器攻擊影響有限(依賴緩存)。
-
-
重定向攻擊:
-
攻擊方式:
-
中間人攻擊:截獲用户 DNS 查詢,偽造錯誤 IP(如將www.bank.com指向釣魚網站 IP);
-
DNS 中毒:向名字服務器發送偽造的 RR 記錄,使其緩存錯誤映射;
-
-
防護難點:需分佈式截獲和偽造,技術門檻高,實際成功案例少。
-
-
利用 DNS 的 DDoS 放大攻擊:
- 攻擊方式:偽造目標 IP 發送 DNS 查詢(查詢報文小),服務器返回大量 RR 記錄(響應報文大),利用 “響應> 查詢” 的流量差攻擊目標;
- 效果:放大倍數有限(通常 10-100 倍),且易被運營商檢測,影響較小。
-
-
總體健壯性:DNS 通過 “多根冗餘、分佈式解析、緩存優化、流量防護”,成為 Internet 中可靠性最高的應用層服務之一。
2.5.7DNS 核心知識點總結
-
本質:應用層基礎性服務,為其他應用(Web、FTP、Email)提供 “域名→IP” 轉換支撐;
-
核心設計:層次化名字空間(解決命名)+ 分佈式解析(解決轉換)+ 資源記錄(解決維護);
-
關鍵特性:
-
複雜性在邊緣(端系統應用層),核心網絡無 DNS 功能;
-
依賴 UDP 53 端口,輕量快速;
-
緩存優化性能,TTL 保證一致性;
-
支持別名轉換、負載均衡等擴展功能;
-
-
核心價值:連接人類 “易記域名” 與網絡 “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 個排隊的鄰居發送塊(“優化疏通試探”);
- 目的:避免錯過高帶寬潛力節點(如某排隊節點實際帶寬高但未被發現),提升全網整體傳輸速率;
- 良性循環實例:
- Alice 隨機向 Bob 發送塊(優化疏通);
- Bob 成為 Alice 的 top4 帶寬提供者,開始向 Alice 提供高帶寬服務;
- Bob 成為 Alice 的 top4,Alice 繼續優先服務 Bob,雙方帶寬持續提升。
2.6.4P2P 文件共享的核心問題與解決方案
P2P 文件共享需解決 2 大核心問題:資源定位(找到有目標文件的 Peer)、節點動態管理(處理 Peer 加入 / 退出),分三類解決方案:
(1)集中式目錄
①工作原理
- Peer 註冊:Peer 上線時向中心目錄服務器上報 “自身 IP + 共享文件列表”;
- 資源查詢:用户(如 Alice)輸入關鍵字(如 “雙截棍.MP3”),客户端向目錄服務器請求;
- 文件傳輸:服務器返回有該文件的 Peer 列表(如 Bob),Alice 與 Bob 直接建立 HTTP 連接下載;
- 資源更新:Alice 下載完成後,向目錄服務器註冊該文件,成為新的服務節點(可向他人提供下載)。
②問題
- 單點故障:目錄服務器宕機則整個系統癱瘓;
- 性能瓶頸:百萬級 Peer 同時註冊 / 查詢時,服務器負載過高;
- 版權風險:服務器易被定位,版權方可追責(Napster 因提供非授權 MP3 目錄服務被關閉)。
(2)全分佈式
①架構特點
- 無中心服務器,Peer 通過 TCP 連接構成 “覆蓋網(Overlay Network)”—— 邏輯網絡,邊為 Peer 間的協作關係(非物理鏈路,如 X 與 Y 有 TCP 連接則為鄰居);
- 協議開源:任何人可實現 Gnutella 客户端(類似 HTTP 與瀏覽器的關係),支持多版本互通。
②資源定位:查詢洪泛(Flooding)
- Alice 向所有鄰居發送查詢請求(如 “雙截棍.MP3”);
- 鄰居收到請求後,除 “入站 Peer” 外,向所有其他鄰居轉發請求;
- 擁有文件的 Peer(如 Bob)沿原路徑反向返回 “查詢命中” 消息;
- Alice 收到消息後,直接與 Bob 建立連接下載。
③優化與問題(老師補充)
- 查詢優化:
- TTL(生存時間):設置跳數限制(如 5-7 跳),避免查詢無限循環;
- 記錄已轉發查詢:避免重複轉發同一請求;
- 問題:
- 覆蓋網構建複雜:新 Peer 需通過 “死黨列表”(軟件配置的常在線 Peer IP)發起 Ping,接收 Pong 後選 8-10 個鄰居;
- 查詢效率低:泛洪導致網絡負載大,實際使用中 “難以找到資源”,後期開源仍未普及。
(3)混合體
①架構設計
- Peer 分兩類:組長(Super Peer) 和組員(Ordinary Peer);
- 層級關係:組員僅連接 1 個組長,組長間建立 TCP 連接構成骨幹網;
- 集中與分佈式結合:組內集中(組長跟蹤組員內容),組間分佈式(組長間轉發查詢)。
②資源定位流程
- 組員向組長髮送關鍵字查詢(如 “周杰倫 - 青花瓷.MP3”);
- 組長匹配組員共享內容,若命中則返回 “文件哈希值 + Peer IP”;
- 若未命中,組長向其他組長轉發查詢,接收結果後彙總返回;
- 組員用 “文件哈希值”(唯一標識,避免同名文件混淆)向目標 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背景:視頻業務的重要性與核心挑戰
-
視頻是互聯網殺手級應用
-
定義:佔網絡流量比重大(七八成甚至更高)、最能吸引用户的業務。
-
核心問題:如何向百萬級併發用户提供高質量的視頻播放服務?
- 傳統方案侷限:早期服務器僅支持幾十 / 幾百併發,無法滿足大規模需求。
-
-
兩大核心挑戰
-
規模性挑戰:需同時向海量用户提供 “流化服務”(實時播放)。
-
異構客户端挑戰:不同設備需求差異大(手機需低解析度,100 寸電視需高解析度(如 1080P)),且設備處理能力、網絡帶寬不一致。
-
2.7.2視頻基礎與壓縮技術
-
視頻的本質
-
視頻是圖像序列:依賴人眼 “視網膜滯留效應”(圖像消失後滯留若干毫秒),幀率常見 24 幀 / 秒(電影)、60 幀 / 秒(遊戲)。
-
圖像是像素的有序序列(Pixel 序列)。
-
-
視頻必須壓縮的原因與原理
-
原因:未壓縮視頻帶寬極大(遠超網絡承載能力),需通過壓縮降低碼率。
-
壓縮基礎:利用視頻的 “空間冗餘” 和 “時間冗餘”
-
空間冗餘:同一幀內像素顏色相似(如藍天區域),可描述 “某像素值持續多少個像素”。
-
時間冗餘:相鄰幀中 “不動的部分多、動的部分少”(如人物説話時,背景不變),僅傳輸動的部分。
-
-
-
壓縮標準與編碼技術
-
碼率類型
-
CBR(固定碼率):壓縮後碼率固定(如 1M/2Mbps),適合帶寬穩定場景。
-
VBR(可變碼率):靜態場景(如風景)碼率低,動態場景(如打鬥)碼率高,更節省帶寬。
-
-
編碼標準
-
國際標準:H.264(AVC)、H.265(HEVC)。
-
我國標準:IVS(高級視頻編碼),由科大吳峯校長助理(原院長)與導師高文院士聯合提出,屬國際標準。
-
-
(3)可伸縮編碼(科大優勢):由科大信息學院李衞平千人提出,可根據設備需求提供不同解析度(如手機 320×240、PC 1920×1080、電視 4K),適配異構客户端。
-
2.7.3視頻點播的流化服務:Streaming 與 DASH
-
流化服務(Streaming) vs 下載播放(Download and Play)
-
下載播放:全量下載視頻文件後再播放,等待時間長(如幾 G 文件需幾小時),體驗差。
-
流化服務:邊下載邊播放(客户端有緩衝區),大幅減少播放延遲(緩衝 7-8 秒即可開始,會員無廣告更快),後續章節會講 RTP 協議封裝流化內容。
-
-
DASH(動態自適應 HTTP 流化):解決異構與網絡差異
-
定義:基於 HTTP 的動態自適應流化技術,適配不同客户端和網絡狀況。
-
核心原理:
- (1)視頻預處理:將視頻切成8-10 秒的塊,每塊生成 “低 / 中 / 高解析度”“不同編碼” 的多個版本。
- (2)Manifest 文件(告示文件):記錄視頻關鍵信息 —— 視頻描述、塊數量、每塊持續時間、各版本塊的 URL(存儲位置)。
-
客户端流程:
-
先下載 Manifest 文件並解析;
-
根據實時網絡帶寬(測帶寬)、屏幕尺寸(設備需求)、緩衝區剩餘量(避免卡頓),動態選擇請求的塊:
-
帶寬大 + 緩衝區滿:請求高解析度塊(提升體驗);
-
帶寬小 + 緩衝區快空:請求低解析度塊(避免 “努力緩衝中” 卡頓)。
-
-
-
DASH 的侷限:若所有客户端都向 “少數源服務器” 請求塊,會出現 3 個問題:
- ① 客户端到服務器跳數多(網絡質量不可控);
- ② 網絡重複流量多(多人下同一視頻,浪費資源);
- ③ 源服務器單點故障 / 性能瓶頸(併發過高崩潰)。
-
2.7.4CDN(內容分發網絡):解決 DASH 侷限,實現內容加速
-
CDN 的定義與目標
-
定義:在應用層構建的 “內容分發網絡”,通過分佈式緩存節點,讓用户 “靠近內容” 獲取服務。
-
目標:解決源服務器集中的問題(跳數多、重複流量、單點故障 / 擁塞),提升視頻播放質量。
-
-
CDN 的核心角色
-
新增角色:CDN 運營商(如美國阿卡米、中國藍訊),ICP(內容提供商,如 CCTV、百度、網飛)需購買 CDN 服務。
-
原有角色:終端用户、ISP、ICP(源服務器)。
-
-
CDN 工作原理(三步)
- 部署緩存節點:CDN 運營商在全球範圍部署緩存節點(存儲視頻塊)。
- 內容預先部署:ICP(如 CCTV)將視頻內容通過專線,預先部署到 CDN 的緩存節點。
- 用户訪問重定向:用户請求時,通過 “域名解析重定向”,引導至 “離用户最近、服務質量最好” 的緩存節點,由緩存節點提供流化服務(內容加速)。
-
CDN 緩存節點部署策略(兩種)
| 策略名稱 | 部署位置 | 優勢 | 劣勢 | 代表案例 |
|---|---|---|---|---|
| In-to-Deep(深入羣眾) | local ISP 內部(靠近用户) | 跳數少、帶寬大、服務質量高 | 節點數量多(數千個)、維護成本高 | 阿卡米 |
| Bring Home(關鍵少數) | 高層 ISP / 數據中心關鍵節點 | 節點數量少、維護成本低 | 到用户跳數稍多 | 中小型 CDN 運營商 |
- CDN 的實際應用實例
實例 1:CCTV 春晚(高併發場景)
-
問題:春晚點播量驚人,若全從 CCTV 源服務器請求,源服務器併發扛不住,且用户到源服務器跳數多(卡頓)。
-
解決方案:CCTV 購買 “中國藍訊” CDN 服務,將春晚視頻通過專線部署到藍訊全國緩存節點,用户由緩存節點服務 —— 跳數少、無卡頓,體驗好。
實例 2:網飛(Netflix)
- 網飛模式:

- 輕資產運營:認證服務器自維護(保障賬號安全),視頻製作、網頁服務租用亞馬遜雲(降低成本);
- 內容分發:製作完的視頻發佈到 CDN 運營商(Level 3、阿卡米)的緩存節點;
- 用户流程:賬號認證→瀏覽雲網頁→點視頻鏈接→域名解析重定向到近的緩存節點→緩存節點提供 DASH 服務。
2.7.5CDN 的關鍵技術:域名解析重定向
-
核心邏輯:通過域名解析,透明引導用户到近的緩存節點,用户無感知(不知道是源服務器還是緩存節點服務)。
-
詳細流程(以 “用户 Bob 訪問 Net Cinema 視頻” 為例):
- Bob 點視頻鏈接(含域名),瀏覽器向 “local DNS” 請求解析該域名;
- local DNS 找到 “Net Cinema(ICP)的權威 DNS”,詢問 IP;
- ICP 權威 DNS 不返回 IP,而是重定向:“請解析 CDN 運營商(King CDN)的域名”;
- local DNS 向 “King CDN 的權威 DNS” 請求解析;
- CDN 權威 DNS 根據 “Bob 的位置”“節點負載”,返回 “離 Bob 最近的緩存節點 IP”;
- Bob 向該緩存節點請求 DASH 服務(下 Manifest→選塊→播放)。
- 透明性:web 端、客户端無需任何修改,僅需在 ICP 權威 DNS(配置重定向)、CDN 權威 DNS(維護節點 IP 與距離)做配置。
2.7.6CDN 的特點與挑戰
-
CDN 的 OTT 特點(Over the Top)
- 含義:在應用層、網絡邊緣(緩存節點是主機)提供服務,不依賴網絡核心設備,靠主機間配合實現加速(互聯網 “Everything over IP” 架構的體現)。
-
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))- sad是sockaddr_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)- cad是sockaddr_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))- sad是sockaddr_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=TCP
if (clientSocket < 0) { perror("socket error"); return; }
// 3. 初始化sockaddr_in結構體(服務器地址信息)
memset((char *)&sad, 0, sizeof(sad)); // 清空結構體,避免垃圾數據
sad.sin_family = AF_INET; // 協議族:TCP/IP
sad.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/IP
sad.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關鍵注意事項
- 網絡字節序轉換:端口號必須用
htons()轉換(主機字節序→網絡字節序),否則不同架構(大端 / 小端)的設備會解析錯誤(如客户端發送端口 777,服務器可能解析為 30592)。 - 阻塞函數:
accept()、connect()、read()均為阻塞函數 —— 無數據 / 連接時,程序停滯,需等待事件發生(如客户端連接、數據到達)。 - 套接字區分:歡迎套接字(
welcomeSocket)僅用於接受連接,不可用於通信;連接套接字(connectionSocket)僅用於單個客户端通信,通信結束必須關閉。 - 客户端隱式綁定:客户端無需
bind,操作系統自動分配空閒端口,避免端口衝突(服務器必須bind固定端口,否則客户端無法找到)。 - 域名解析失敗:若
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)) |
sad 是 sockaddr_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_INET、sin_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_in 的 sin_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區分不同客户端。
2.10小結
2.10.1應用進程體系架構
-
核心分類
應用進程通信的體系架構分為三類:
-
客户端 / 服務器(C/S)模式
-
P2P(對等)模式
-
混合模式(融合 C/S 與 P2P 特性)
-
2.10.2傳輸層服務與服務質量
-
服務依賴關係
應用層需藉助傳輸層提供的服務實現通信,傳輸層服務質量(QoS)決定應用層通信性能。
-
QoS 核心指標
-
可靠性(數據是否完整無丟失)
-
帶寬(傳輸速率)
-
延遲(數據傳輸耗時)
-
安全性(是否具備加密等保護機制)
-
2.10.3TCP/IP 協議棧的傳輸層服務
| 協議 | 核心特性 | 服務類型 |
|---|---|---|
| TCP | 面向連接、可靠傳輸 | 字節流服務 |
| UDP | 無連接、不可靠傳輸 | 報文服務 |
注:文稿中 “TCPRP 協議” 修正為 “TCP/IP 協議”,“UDB” 修正為 “UDP”。
2.10.4典型應用層協議
-
核心協議分類
-
網頁服務:HTTP 協議
-
文件傳輸:FTP 協議
-
電子郵件:SMTP/POP3/IMAP 協議
-
域名解析:DNS 系統
-
內容分發:CDN 技術
-
注:文稿中 “HTTPFT” 修正為 “HTTP、FTP”。
2.10.5Socket 編程基礎
-
編程接口類型
-
TCP Socket 編程(基於可靠連接)
-
UDP Socket 編程(基於無連接報文)
-
注:文稿中 “TCB 的 soccer” 修正為 “TCP Socket”。
2.10.6應用報文結構與傳輸
-
報文分類(按交互方向)
-
請求報文(客户端向服務器發送)
-
響應報文(服務器向客户端返回)
-
-
報文格式(通用結構)
-
報文頭(控制信息,如協議版本、地址等)
-
報文體(實際傳輸的數據內容)
注:文稿中 “豹紋” 修正為 “報文”。
-
-
報文分類(按用途)
-
數據報文(傳輸業務數據)
-
控制報文(傳輸控制信息)
-
-
傳輸模式
-
帶內傳輸:控制信息與數據在同一 TCP 連接中傳輸
-
帶外傳輸:控制信息與數據通過兩個獨立連接傳輸
-
2.10.7客户端 / 服務器模式細節
-
目錄維護方式
-
集中式(由中心服務器統一管理目錄)
-
分散式(目錄分佈在多個節點)
-
-
客户端狀態管理
-
有狀態:服務器維護客户端的會話信息
-
無狀態:服務器不保存客户端狀態數據
-
2.10.8章節核心結論
-
傳輸層可提供可靠或不可靠服務,適配不同應用需求
-
應用層複雜性主要在網絡邊緣(終端設備)處理,核心網保持簡化
參考資料來源:中科大鄭烇、楊堅全套《計算機網絡(自頂向下方法 第7版,James F.Kurose,Keith W.Ross)》課程