重慶金融網(wǎng)站建設(shè)一級域名二級域名三級域名的區(qū)別
文章目錄
- 零、前言
- 一、應(yīng)用層協(xié)議原理
- 1.1 網(wǎng)絡(luò)應(yīng)用的體系結(jié)構(gòu)
- 1.1.1 客戶-服務(wù)器(C/S)體系結(jié)構(gòu)
- 1.1.2 對等體(P2P)體系結(jié)構(gòu)
- 1.1.3 C/S 和 P2P體系結(jié)構(gòu)的混合體
- 1.2 進(jìn)程通信
- 1.2.1 問題1:對進(jìn)程進(jìn)行編址(addressing)(服務(wù)用戶)
- 1.2.2 問題2:傳輸層提供的服務(wù)
- 1.2.2.1 需要穿過層間的信息
- 1.2.2.2 層間信息的代表
- 1.2.2.3 TCP 之上的套接字(socket)
- 1.2.2.4 UDP socket
- 1.2.2.5 UDP之上的套接字(socket)
- 1.2.2.6 套接字(socket)
- 1.2.3 如何使用傳輸層提供的服務(wù)實現(xiàn)應(yīng)用
- 1.3 應(yīng)用層協(xié)議
- 1.3.1 應(yīng)用需要傳輸層提供什么樣的服務(wù)?如何描述傳輸層的服務(wù)?
- 1.3.2 Internet 傳輸層提供的服務(wù)
- 1.3.3 UDP 存在的必要性
- 1.3.4 Internet應(yīng)用及其應(yīng)用層協(xié)議和傳輸協(xié)議
- 1.3.5 安全TCP
- 二、Web 和 HTTP
- 2.1 HTTP概況
- 2.2 HTTP 連接
- 2.2.1 非持久HTTP連接
- 2.2.2 響應(yīng)時間模型
- 2.2.3 持久HTTP
- 2.3 HTTP 請求報文
- 2.3.1 通用格式
- 2.3.2 提交表單輸入
- 2.3.3 方法類型
- 2.4 HTTP響應(yīng)報文
- 2.4.1 HTTP 響應(yīng)狀態(tài)碼
- 2.4.2 Trying out HTTP (client side) for yourself
- 2.5 用戶-服務(wù)器狀態(tài):cookies
- 2.6 Web 緩存(代理服務(wù)器)
- 2.6.1 條件GET方法
- 三、FTP
- 3.1 FTP: 控制連接與數(shù)據(jù)連接分開
- 3.2 FTP 命令, 響應(yīng)
- 四、Email
- 4.1 Email:郵件服務(wù)器
- 4.2 Email:SMTP[RFC 2821]
- 4.3 簡單的SMTP交互
- 4.4 SMTP 總結(jié)
- 4.5 郵件報文格式
- 4.6 報文格式:多媒體擴(kuò)展
- 4.7 郵件訪問協(xié)議
- 4.7.1 POP3協(xié)議
- 4.7.2 POP3 與 IMAP協(xié)議
- 五、DNS
- 5.1 DNS 的必要性
- 5.2 DNS(domain name system) 系統(tǒng)需要解決的問題?
- 5.3 DNS 的歷史
- 5.4 DNS(Domain Name system)總體思路和目標(biāo)
- 5.5 問題1:DNS名字空間(The DNS Name Space)
- 5.5.1 DNS: 根名字服務(wù)器
- 5.5.2 DNS 名字空間
- 5.6 問題2:解析問題——名字服務(wù)器(Name Server)
- 5.6.1 名字空間劃分為若干區(qū)域:Zone
- 5.6.2 TLD 服務(wù)器
- 5.6.3 區(qū)域名字服務(wù)器維護(hù)資源記錄
- 5.6.4 DNS(Domain Name System)
- 5.6.5 本地名字服務(wù)器(Local Name Server)
- 5.6.6 ★遞歸查詢
- 5.6.7 迭代查詢
- 5.6.8 DNS 協(xié)議、報文
- 5.6.9 提高性能:緩存
- 5.7 問題3:維護(hù)問題:新增一個域
- 5.7.1 攻擊DNS
- 六、P2P應(yīng)用
- 6.1 純P2P架構(gòu)
- 6.2 文件分發(fā):C/S vs P2P
- 6.2.1 文件分發(fā)時間:C/S模式
- 6.2.2 文件分發(fā)時間:P2P模式
- 6.2.3 Client-server vs. P2P
- 6.2.4 P2P文件共享
- 6.2.5 非結(jié)構(gòu)化P2P
- 6.2.5.1 P2P:集中式目錄
- 6.2.5.2 查詢洪泛:Gnutella(完全分布式)
- 6.2.5.3 利用不勻稱性:KaZaA(混合體)
- 6.2.5.4 P2P文件分發(fā):BitTorrent
- 6.2.6 DHT(結(jié)構(gòu)化P2P)
- 七、CDN
- 7.1 視頻流化服務(wù)和CDN:上下文
- 7.2 多媒體:視頻
- 7.3 存儲視頻的流化服務(wù)
- 7.3.1 多媒體流化服務(wù):DASH
- 7.3.2 流式多媒體技術(shù)3:DASH
- 7.4 內(nèi)容分發(fā)網(wǎng)(Content Distribution Networks)
- 八、TCP/IP Socket編程快速入門
- 8.1 創(chuàng)建簡單服務(wù)器
- 8.2 客戶端
- 8.3 并發(fā)多客戶端通信
- 8.3.1 多線程的Socket 服務(wù)器
- 8.4 簡易HTTP服務(wù)器
- 九、TCP 套接字編程
- 9.1 Socket 編程
- 9.2 TCP套接字編程
- 9.3 數(shù)據(jù)結(jié)構(gòu) sockaddr_in
- 9.4 數(shù)據(jù)結(jié)構(gòu) hostent
- 9.5 例子:C客戶端(TCP)
- 9.6 例子:C服務(wù)器(TCP)
- 十、UDP 套接字編程
- 10.1 Client/server socket 交互:UDP
- 10.2 樣例:C客戶端(UDP)
- 1.3 樣例:C服務(wù)器(UDP)
零、前言
網(wǎng)絡(luò)應(yīng)用是計算機(jī)網(wǎng)絡(luò)存在的理由。
如果我們不能構(gòu)想出任何有用的應(yīng)用, 也就沒有必要去設(shè)計支持它們的網(wǎng)絡(luò)協(xié)議了。
目標(biāo):
- 網(wǎng)絡(luò)應(yīng)用的原理:網(wǎng)絡(luò)應(yīng)用協(xié)議的概念和實現(xiàn)方面
- 傳輸層的服務(wù)模型
- 客戶-服務(wù)器模式
- 對等模式(peer-to-peer)
- 內(nèi)容分發(fā)網(wǎng)絡(luò)
- 網(wǎng)絡(luò)應(yīng)用的實例:互聯(lián)網(wǎng)流行的應(yīng)用層協(xié)議
- HTTP
- FTP
- SMTP / POP3 / IMAP / DNS
- 編程:網(wǎng)絡(luò)應(yīng)用協(xié)議
- socket API
創(chuàng)建一個新的網(wǎng)絡(luò)應(yīng)用
-
編程
- 在不同的端系統(tǒng)上運(yùn)行
- 通過網(wǎng)絡(luò)基礎(chǔ)設(shè)施提供的服務(wù),應(yīng)用進(jìn)程彼此通信
- 如Web:
- Web 服務(wù)器軟件與瀏覽器軟件通信
-
網(wǎng)絡(luò)核心中沒有應(yīng)用層軟件
- 網(wǎng)絡(luò)核心中沒有應(yīng)用層功能
- 網(wǎng)絡(luò)應(yīng)用只在端系統(tǒng)上存在,快速網(wǎng)絡(luò)應(yīng)用開發(fā)和部署
一、應(yīng)用層協(xié)議原理
1.1 網(wǎng)絡(luò)應(yīng)用的體系結(jié)構(gòu)
可能的應(yīng)用架構(gòu):
- 客戶-服務(wù)器模式(C/S : client / server)
- 對等模式(P2P: Peer To Peer)
- 混合體:
1.1.1 客戶-服務(wù)器(C/S)體系結(jié)構(gòu)
- 服務(wù)器
- 一直運(yùn)行
- 固定的 IP 地址和周知的端口號(約定)
- 擴(kuò)展性:服務(wù)器場
- 數(shù)據(jù)中心進(jìn)行擴(kuò)展
- 擴(kuò)展性差
- 客戶端
- 主動與服務(wù)器通信
- 與互聯(lián)網(wǎng)有間歇性的連接
- 可能是動態(tài)IP地址
- 不直接與其它客戶端通信
1.1.2 對等體(P2P)體系結(jié)構(gòu)
- (幾乎)沒有一直運(yùn)行的服務(wù)器
- 任意端系統(tǒng)之間可以進(jìn)行通信
- 每一個節(jié)點(diǎn)既是客戶端又是服務(wù)器
- 自擴(kuò)展性-新peer 節(jié)點(diǎn)帶來新的服務(wù)能力,當(dāng)然也帶來了新的服務(wù)請求
- 參與的主機(jī)間歇性連接且可以改變IP地址
- 難以管理
- 例子:Gnutella,迅雷
1.1.3 C/S 和 P2P體系結(jié)構(gòu)的混合體
Napster
- 文件搜索:集中
- 主機(jī)在中心服務(wù)器上注冊其資源
- 主機(jī)向中心服務(wù)器查詢資源位置
- 文件傳輸:P2P
- 任意Peer節(jié)點(diǎn)之間
即時通信
- 在線檢測:集中
- 當(dāng)用戶上線時,向中心服務(wù)器注冊其IP地址
- 用戶與中心服務(wù)器聯(lián)系,以找到其在線好友的位置
- 兩個用戶之間聊天:P2P
1.2 進(jìn)程通信
進(jìn)程:在主機(jī)上運(yùn)行的應(yīng)用程序
- 在同一個主機(jī)內(nèi),使用進(jìn)程間通信機(jī)制通信(操作系統(tǒng)定義)
- 不同主機(jī),通過交換**報文(Message)**來通信
- 使用OS提供的通信服務(wù)
- 按照應(yīng)用協(xié)議交換報文
- 借助傳輸層提供的服務(wù)
對于每對通信進(jìn)程:
一個標(biāo)識為 客戶端進(jìn)程:發(fā)起通信的進(jìn)程
另一個為 服務(wù)器進(jìn)程:等待連接的進(jìn)程
- 注意:P2P架構(gòu)的應(yīng)用也有客戶端進(jìn)程和服務(wù)器進(jìn)程之分
分布式應(yīng)用進(jìn)程需要解決的問題
- 問題1:進(jìn)程標(biāo)示和尋址問題**(服務(wù)用戶)**
- 問題2:傳輸層-應(yīng)用層提供服務(wù)是如何**(服務(wù))**
- 位置:層間界面的SAP(TCP/IP: socket)
- 形式:應(yīng)用程序接口API(TCP/IP:socket API)
- 問題3:如何使用傳輸層提供的服務(wù),實現(xiàn)應(yīng)用進(jìn)程之間的報文交換,實現(xiàn)應(yīng)用**(用戶使用服務(wù))**
- 定義應(yīng)用層協(xié)議:報文格式,解釋,時序等
- 編制程序,使用OS提供的API,調(diào)用網(wǎng)絡(luò)基礎(chǔ)設(shè)施提供通信服務(wù)傳報文,實現(xiàn)應(yīng)用時序等;
1.2.1 問題1:對進(jìn)程進(jìn)行編址(addressing)(服務(wù)用戶)
-
進(jìn)程為了接收報文,必須有一個標(biāo)識
即:SAP(發(fā)送也需要標(biāo)示)
- 主機(jī):唯一的32位IP地址
- 僅僅有IP地址不能夠唯一標(biāo)示一個進(jìn)程:在一臺端系統(tǒng)上有很多應(yīng)用進(jìn)程在運(yùn)行
- 所采用的傳輸層協(xié)議:TCP or UDP
- 端口號(Port Numbers)
- 主機(jī):唯一的32位IP地址
-
一些知名端口號例子:
- HTTP: TCP 80 Mail:TCP25 ftp:TCP2
-
一個進(jìn)程:用IP + Port 標(biāo)示 端節(jié)點(diǎn)
-
本質(zhì)上,一個主機(jī)進(jìn)程之間的通信由2個端節(jié)點(diǎn)構(gòu)成
1.2.2 問題2:傳輸層提供的服務(wù)
1.2.2.1 需要穿過層間的信息
- 層間接口必須要攜帶的信息
- 要傳輸?shù)膱笪?#xff08;對于本層來說:SDU)
- 誰傳的:對方的應(yīng)用進(jìn)程的標(biāo)示:IP + TCP(UDP) 端口
- 傳給誰:對方的應(yīng)用進(jìn)程的標(biāo)示:對方的 IP + TCP(IDP) 端口
- 傳輸層實體(TCP 或者 UDP 實體)根據(jù)這些信息進(jìn)行 TCP報文段(UDP 數(shù)據(jù)報)的封裝
- 源端口號,目標(biāo)端口號,數(shù)據(jù)等
- 將 IP 地址往下交 IP 實體,用于封裝 IP 數(shù)據(jù)報:源 IP,目標(biāo) IP
1.2.2.2 層間信息的代表
- 如果 Socket API 每次傳輸報文,都攜帶如此多的信息,太繁瑣易錯,不便于管理
- 用個代號標(biāo)示通信的雙方或者單方:socket
- 就像OS打開文件返回的句柄一樣
- 對句柄的操作,就是對文件的操作
- TCP socket:
- TCP 服務(wù),兩個進(jìn)程之間的通信需要之前要建立連接
- 兩個進(jìn)程通信會持續(xù)一段時間,通信關(guān)系穩(wěn)定
- 可以用一個整數(shù)表示兩個應(yīng)用實體之間的通信關(guān)系,本地標(biāo)示
- 穿過層間接口的信息量最小
- TCP socket:源IP,源端口,目標(biāo)IP,目標(biāo)端口
- TCP 服務(wù),兩個進(jìn)程之間的通信需要之前要建立連接
1.2.2.3 TCP 之上的套接字(socket)
對于使用面向連接服務(wù)(TCP)的應(yīng)用而言,套接字是4元組的一個具有本地意義的標(biāo)識。
- 4元組:(源IP,源port,目標(biāo)IP,目標(biāo)port)
- 唯一的指定了一個會話(2個進(jìn)程之間的會話關(guān)系)
- 應(yīng)用使用這個標(biāo)示,與遠(yuǎn)程的應(yīng)用進(jìn)程通信
- 不必在每一個報文的發(fā)送都指定這4元組
- 就像使用操作系統(tǒng)打開一個文件,OS返回一個文件句柄一樣,以后使用這個文件句柄,而不是使用這個文件的目錄名、文件名
- 簡單,便于管理
TCP 不只是一個簡單標(biāo)識,它主要是用于指明應(yīng)用進(jìn)程會話的本地標(biāo)識。
1.2.2.4 UDP socket
UDP socket:
- UDP 服務(wù),兩個進(jìn)程之間的通信需要之前無需建立連接
- 每個報文都是獨(dú)立傳輸?shù)?/li>
- 前后報文可能給不同的分布式進(jìn)程
- 因此,只能用一個整數(shù)表示本應(yīng)用實體的標(biāo)示
- 因為這個報文可能傳給另一個分布式進(jìn)程
- 穿過層間接口的信息大小最小
- UDP socket:本地IP,本地端口
- 但是傳輸報文時:必須提供對方IP,port
- 接收報文時:傳輸層需要上傳對方的IP,port
1.2.2.5 UDP之上的套接字(socket)
- 對于使用無連接服務(wù)(UDP)的應(yīng)用而言,套接字是2元組的一個具有本地意義的標(biāo)示
- 2元組:IP,port(源端指定)
- UDP 套接字指定了應(yīng)用所在的一個端節(jié)點(diǎn)(end point)
- 在發(fā)送數(shù)據(jù)報時,采用創(chuàng)建好的本地套接字(標(biāo)示ID),就不必在發(fā)送每個報文中指明自己所采用的 ip 和 port
- 但是在發(fā)送報文時,必須要指定對方的 ip 和 udp port(另外一個端節(jié)點(diǎn))
1.2.2.6 套接字(socket)
- 進(jìn)程向套接字發(fā)送報文或從套接字接收報文
- 套接字<->門戶
- 發(fā)送進(jìn)程將報文推出門戶,發(fā)送進(jìn)程依賴于傳輸層設(shè)施在另外一側(cè)的門將報文交付給接受進(jìn)程
- 接收進(jìn)程從另外一端的門戶收到報文(依賴于傳輸層設(shè)施)
1.2.3 如何使用傳輸層提供的服務(wù)實現(xiàn)應(yīng)用
- 定義應(yīng)用層協(xié)議:報文格式、解釋、時序等
- 編制程序,通過 API 調(diào)用網(wǎng)絡(luò)基礎(chǔ)設(shè)施提供通信服務(wù)傳報文,解析報文,實現(xiàn)應(yīng)用時序等
1.3 應(yīng)用層協(xié)議
應(yīng)用層協(xié)議定義了:運(yùn)行在不同端系統(tǒng)上的應(yīng)用進(jìn)程如何相互交換報文
- 交換的報文類型:請求和應(yīng)答報文
- 各種報文類型的語法:報文中的各個字段及其描述
- 字段的語義:即字段取值的含義
- 進(jìn)程何時、如何發(fā)送報文及對報文進(jìn)行響應(yīng)的規(guī)則
應(yīng)用協(xié)議僅僅是應(yīng)用的一個組成部分
公開協(xié)議:
- 由RFC文檔定義
- 允許互操作
- 如HTTP,SMTP
專用(私有)協(xié)議:
- 協(xié)議不公開
- 如:Skype
1.3.1 應(yīng)用需要傳輸層提供什么樣的服務(wù)?如何描述傳輸層的服務(wù)?
數(shù)據(jù)丟失率
- 有些應(yīng)用則要求100%的可靠數(shù)據(jù)傳輸(如文件)
- 有些應(yīng)用(如音頻)能容忍一定比例一下的數(shù)據(jù)丟失
延遲
- 一些應(yīng)用 處于有效性考慮,對數(shù)據(jù)傳輸有嚴(yán)格的時間限制
- Internet 電話、交互式游戲
- 延遲、延遲差
吞吐
- 一些應(yīng)用(如多媒體)必須需要最小限度的吞吐,從而使得應(yīng)用能夠有效運(yùn)轉(zhuǎn)
- 一些應(yīng)用能充分利用可供使用的吞吐(彈性應(yīng)用)
安全性
- 機(jī)密性
- 完整性
- 可認(rèn)證性(鑒別)
常見應(yīng)用對于傳輸服務(wù)的要求
1.3.2 Internet 傳輸層提供的服務(wù)
TCP 服務(wù):
- 可靠的傳輸服務(wù)
- 流量控制:發(fā)送方不會淹沒接受方
- 擁塞控制:當(dāng)網(wǎng)絡(luò)出現(xiàn)擁塞時,能抑制發(fā)送方
- 不能提供的服務(wù):時間保證、最小吞吐保證和安全
- 面向連接:要求在客戶端進(jìn)程和服務(wù)器進(jìn)程之間建立連接
UDP 服務(wù):
- 不可靠數(shù)據(jù)傳輸
- 不提供的服務(wù):可靠、流量控制、擁塞控制、時間、帶寬保證、建立連接
UDP 啥都沒有,那為什么有UDP呢?
1.3.3 UDP 存在的必要性
- 能夠區(qū)分不同的進(jìn)程,而IP服務(wù)不能
- 在IP提供的主機(jī)到主機(jī)端到端功能的基礎(chǔ)上,區(qū)分了主機(jī)的應(yīng)用進(jìn)程
- 無需建立連接,省去了建立連接時間,適合事務(wù)性的應(yīng)用
- 不做可靠性的工作,例如檢錯重發(fā),適合那些對實時性要求比較高而對正確性要求不高的應(yīng)用
- 因為為了實現(xiàn)可靠性(準(zhǔn)確性、保序等),必須付出時間代價(檢錯重發(fā))。
- 沒有擁塞控制和流量控制,應(yīng)用能夠按照設(shè)定的速度發(fā)送數(shù)據(jù)
- 而在TCP上面的應(yīng)用,應(yīng)用發(fā)送數(shù)據(jù)的速度和主機(jī)向網(wǎng)絡(luò)發(fā)送的實際速度是不一致的,因為有流量控制和擁塞控制
1.3.4 Internet應(yīng)用及其應(yīng)用層協(xié)議和傳輸協(xié)議
1.3.5 安全TCP
TCP & UDP
- 都沒有加密
- 明文通過互聯(lián)網(wǎng)傳輸,甚至密碼
SSL(safe socket level,運(yùn)行在在TCP之上)
- 在TCP上面實現(xiàn),提供加密的TCP連接
- 私密性
- 數(shù)據(jù)完整性
- 端到端的鑒別
這就是為什么我們很多時候網(wǎng)頁都是 https 開頭
https = http + ssl
SSL
------------http
SSL在應(yīng)用層
- 應(yīng)用采用SSL庫,SSL庫使用TCP通信
SSL socket API
- 應(yīng)用通過 API 將明文交給socket,SSL將其加密在互聯(lián)網(wǎng)上傳輸
- 詳見第8章
二、Web 和 HTTP
一些術(shù)語:
-
Web頁:由一些對象組成
-
對象可以是一些HTML文件、JPEG圖像、Java小程序、聲音剪輯文件等
-
Web頁含有一個基本的HTML文件,該基本HTML文件又包含若干對象的引用(鏈接)
-
通過URL對每個對象進(jìn)行引用
- 訪問協(xié)議、用戶名、口令字、端口等
-
URL格式:
2.1 HTTP概況
HTTP:超文本傳輸協(xié)議
- Web 的 應(yīng)用層協(xié)議
- 客戶/服務(wù)器模式
- 客戶:請求、接收和顯示W(wǎng)eb對象的瀏覽器
- 服務(wù)器:對請求進(jìn)行響應(yīng),發(fā)送對象的Web服務(wù)器
- HTTP 1.0: RFC 1945
- HTTP 1.1: RFC 2068
使用TCP:
-
客戶發(fā)起一個與服務(wù)器的TCP連接(建立套接字),端口號為 80
-
服務(wù)器接受客戶的TCP連接
-
在瀏覽器(HTTP客戶端) 與 Web服務(wù)器(HTTP服務(wù)器 server) 交換HTTP報文 (應(yīng)用層協(xié)議報文)
-
TCP連接關(guān)閉
HTTP是無狀態(tài)的
- 服務(wù)器并不維護(hù)關(guān)于客戶的任何信息
維護(hù)狀態(tài)的協(xié)議很復(fù)雜!
- 必須維護(hù)歷史信息(狀態(tài))
- 如果服務(wù)器/客戶端死機(jī),它們的狀態(tài)信息可能不一致,二者的信息必須是一致
- 無狀態(tài)的服務(wù)器能夠支持更多的客戶端
2.2 HTTP 連接
非持久HTTP連接
- 最多只有一個對象在TCP連接上發(fā)送
- 下載多個對象需要多個TCP連接
- HTTP/1.0 使用非持久連接
持久HTTP
- 多個對象可以在一個(在客戶端和服務(wù)器之間的) TCP 連接上的傳輸
- HTTP/1.1 默認(rèn)使用持久連接
2.2.1 非持久HTTP連接
2.2.2 響應(yīng)時間模型
**往返時間RTT(round-trip time):**一個小的分組從客戶端到服務(wù)器,再回到客戶端的時間(傳輸時間忽略不計)
響應(yīng)時間:
- 一個RTT用來發(fā)起TCP連接
- 一個RTT用來HTTP請求并等待HTTP響應(yīng)
- 文件傳輸時間
共:2RTT + 傳輸時間
2.2.3 持久HTTP
非持久HTTP的缺點(diǎn):
- 每個對象要2個 RTT
- 操作系統(tǒng)必須為每個TCP連接分配資源
- 但瀏覽器通常打開并行TCP連接,以獲取引用對象
持久HTTP
- 服務(wù)器在發(fā)送響應(yīng)后,仍保持 TCP 連接
- 在相同客戶端和服務(wù)器之間的后續(xù)請求和響應(yīng)報文通過相同的連接進(jìn)行傳送
- 客戶端在遇到一個引用對象的時候,就可以盡快發(fā)送該對象的請求
非流水方式的持久HTTP
- 客戶端只能在收到前一個響應(yīng)后才能發(fā)出新的請求
- 每個引用對象花費(fèi)一個RTT
流水方式的持久HTTP
- HTTP/1.1的默認(rèn)模式
- 客戶端遇到一個引用對象就立即產(chǎn)生一個請求
- 所有引用(小)對象只花費(fèi)一個RTT是可能的
2.3 HTTP 請求報文
- 兩種類型的HTTP報文:請求、響應(yīng)
- HTTP請求報文:
- ASCII(人能閱讀)
下面是一個典型的 HTTP 請求報文:
雖然這個特定的報文僅有5行,但一個請求報文能夠具有更多的行或者至少為1行。
HTTP 請求報文的第一行叫做請求行(request line),其后繼的行叫做首部行(header line)
請求行有3個字段:方法字段、URL字段和HTTP版本字段
方法字段可以取不同的值,包括:GET、POST、HEAD、PUT 和 DELETE(絕大多數(shù)HTTP請求報文使用GET方法)
上面首部行的Host則指明了對方主機(jī),雖然該主機(jī)中已經(jīng)有了TCP,但是由于我們后面有 Connection:close,要求不使用持久連接,在發(fā)送完對象后就關(guān)閉連接,所以指明主機(jī)還是必要的
2.3.1 通用格式
2.3.2 提交表單輸入
例如用戶向搜索引擎提供搜索關(guān)鍵詞,HTTP 客戶端通常使用 POST 方法,使用 POST 報文時,用戶仍然可以請求一個Web頁面,Web頁面的特定內(nèi)容依賴于用戶的表單輸入
使用 POST 方式,實體中包含用戶的輸入,而使用GET時,實體為空,不過GET也經(jīng)常用來作為表單提交的方式
學(xué)過一些Web前端的話對這一點(diǎn)不會陌生,<form> 可以指定提交的方式為 POST 或者是 GET
我們在 使用 PHP Web交互編程時,是有 超全局?jǐn)?shù)組 _POST 和 _GET的,都可以獲取用戶的表單輸入
POST方式:
- 網(wǎng)頁通常包括表單輸入
- 包含在實體主體(entity body)中的輸入被提交到服務(wù)器
URL方式:
- 方法:GET
- 輸入通過請求行的URL字段上截
當(dāng)使用GET,比如我們輸入了monkeys和bananas,那么URL就會變成如下形式:
www.somesite.comanimalsearch?monkeys&bananas
當(dāng)然也有參數(shù)名=參數(shù)值的形式(比如我們網(wǎng)盤鏈接有password=xxx)
http://www.baidu.com/s?wd=xx+yy+zzz&cl=3
參數(shù):wd,cl
參數(shù)值:xx+yy+zzz,3
2.3.3 方法類型
HTTP/1.0
- GET
- POST
- HEAD
- 要求服務(wù)器在響應(yīng)報文中不包含請求對象 -> 故障跟蹤
HTTP/1.1
- GET,POST,HEAD
- PUT
- 將實體主體中的文件上載到URL字段規(guī)定的路徑
- DELETE
- 刪除URL字段規(guī)定的文件
2.4 HTTP響應(yīng)報文
我們先看一條典型的 HTTP 響應(yīng)報文
它有三個部分:
- 初始狀態(tài)行(state line)
- 狀態(tài)行有3個字段:協(xié)議版本字段、狀態(tài)碼和相應(yīng)狀態(tài)信息
- 6個首部行(head line)
- 每行含義和英文單詞已知
- 實體體(entity body)
- 報文的主要部分
2.4.1 HTTP 響應(yīng)狀態(tài)碼
位于服務(wù)器→客戶端的響應(yīng)報文中的首行
一些狀態(tài)碼的例子:
200 OK
- 請求成功,請求對象包含在響應(yīng)報文的后續(xù)部分
301 Moved Permanently
- 請求的對象已經(jīng)被永久轉(zhuǎn)移了;新的URL在響應(yīng)報文的Location:首部行中指定
- 客戶端軟件自動用新的URL去獲取對象
400 Bad Request
- 一個通用的差錯代碼,表示該請求不能被服務(wù)器解讀
404 Not Found
- 請求的文檔在該服務(wù)上沒有找到
505 HTTP Version Not Supported
2.4.2 Trying out HTTP (client side) for yourself
這里是在 終端中(windows可以在cmd中)通過telnet 連接目標(biāo)服務(wù)器,然后 輸入一個 GET 請求報文
看看服務(wù)器的響應(yīng)
例子:
我自己瞎搗鼓了下:
返回了一段 html 文本
root@LAPTOP-292TJJC6:~# telnet github.com 80
Trying 20.205.243.166...
Connected to github.com.
Escape character is '^]'.
GET /~ross/ HTTP/1.1
Host: github.com
HTTP/1.1 408 Request Time-out
Content-length: 110
Cache-Control: no-cache
Connection: close
Content-Type: text/html<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>
Connection closed by foreign host.
root@LAPTOP-292TJJC6:~#
2.5 用戶-服務(wù)器狀態(tài):cookies
大多數(shù)主要的門戶網(wǎng)站使用 cookies(為什么我們打開以前打開過的網(wǎng)站能夠恢復(fù)之前的信息?)
4個組成部分:
- 在HTTP響應(yīng)報文中有一個cookie的首部行
- 在HTTP請求報文含有一個cookie的首部行
- 在用戶端系統(tǒng)中保留有一個cookie文件,由用戶的瀏覽器管理
- 在Web站點(diǎn)有一個后端數(shù)據(jù)庫
例子:
- Susan總是用同一個PC使用Internet Explore上網(wǎng)
- 她第一次訪問了一個使用了Cookie的電子商務(wù)網(wǎng)站
- 當(dāng)最初的HTTP請求到達(dá)服務(wù)器時,該Web站點(diǎn)產(chǎn)生一個唯一的ID:1678,并以此作為索引在它的后端數(shù)據(jù)庫中產(chǎn)生一個表項
- Susan 的瀏覽器收到該 HTTP 響應(yīng)報文時,它會看到 Set-cookie:首部。從而在瀏覽器的 cookie 文件中添加一行,該行包括了服務(wù)器的主機(jī)名和Set-cookie:首部中的識別碼
- 當(dāng) Susan 后續(xù)再訪問Amazon,瀏覽器就會查詢cookie 文件并抽取她對Amazon 的識別碼,放到HTTP 請求報文包括識別碼的 cookie 首部行中。
- Amazon 就可以追蹤 Susan 的訪問活動,提供服務(wù)
外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳
Cookies 能帶來什么:
- 用戶驗證
- 購物車
- 推薦
- 用戶狀態(tài)(Web e-mail)
如何維持狀態(tài):
- 協(xié)議端節(jié)點(diǎn):在多個事務(wù)上,發(fā)送端和接收端維持狀態(tài)
- cookies:http報文攜帶狀態(tài)信息
Cookies 與 隱私:
- Cookies 允許站點(diǎn)知道許多關(guān)于用戶的信息
- 可能將它知道的東西賣給第三方
- 使用重定向和cookie 的搜索引擎還能知道用戶更多的信息
- 如通過某個用戶在大量站點(diǎn)上的行為,了解其個人瀏覽方式的大致模式
- 廣告公司從站點(diǎn)獲得信息
2.6 Web 緩存(代理服務(wù)器)
Web 緩存器(Web cache)也叫代理服務(wù)器(proxy server)
目標(biāo):不訪問原始服務(wù)器,就滿足客戶的要求
- 用戶設(shè)置瀏覽器:通過緩存訪問Web
- 瀏覽器將所有的HTTP請求發(fā)給緩存
- 在緩存中的對象:緩存直接返回對象
- 如對象不在緩存,緩存請求原始服務(wù)器,然后再將對象返回給客戶端
- 緩存既是客戶端又是服務(wù)器
- 通常緩存是由ISP安裝(大學(xué)、公司、居民區(qū)ISP)
為什么要使用Web緩存?
- 降低客戶端的請求響應(yīng)時間
- 可以大大減少一個機(jī)構(gòu)內(nèi)部網(wǎng)絡(luò)與Internet 接入鏈路上的流量
- 互聯(lián)網(wǎng)大量采用了緩存:可以使較弱的 ICP 也能夠有效提供內(nèi)容
示例
上圖有兩個網(wǎng)絡(luò):機(jī)構(gòu)(內(nèi)部)網(wǎng)絡(luò)和公共因特網(wǎng)
- 機(jī)構(gòu)網(wǎng)絡(luò)上一臺服務(wù)器和因特網(wǎng)上的路由器通過 15Mbps 的鏈路連接
- 對象平均長度:1Mb
- 機(jī)構(gòu)內(nèi)瀏覽器到初始服務(wù)器平均訪問速率:15個請求每秒
- 我們假設(shè)HTTP請求報文小到可以忽略,因而不計其在網(wǎng)絡(luò)以及接入鏈路上的時延
- 接入鏈路一側(cè)路由器轉(zhuǎn)發(fā)請求報文到接收響應(yīng)報文,我們稱為“因特網(wǎng)時延”,假設(shè)時間平均為2s
那么局域網(wǎng)上的流量強(qiáng)度為:15個 / s * 1Mb / 100Mbps = 0.15
接入鏈路上的流量強(qiáng)度:15個 / s * 1Mb / 請求 / 15Mbps = 1
流量強(qiáng)度為1,排隊時延無限大,因而鏈路時延在分鐘量級, 響應(yīng)極慢
解決方式:
-
增加接入鏈路帶寬, 不妨從15Mbps 升級到 100Mbps, 這樣響應(yīng)時間降低到大概2s
-
另一種方案, 在機(jī)構(gòu)網(wǎng)絡(luò)中安裝Web緩存器, 我們這里假設(shè)命中率為0.4, 命中情況下時延在10ms以內(nèi), 此時鏈路只會處理60%的請求對象, 流量強(qiáng)度降低到0.6, 一般流量強(qiáng)度低于0.8 的時延為幾十毫秒
那么 平均時延為 0.4 * 0.01 + 0.6 * 2.1 約等于 1.2 s
Web 緩存相較于升級鏈路, 代價低, 收益高
2.6.1 條件GET方法
緩存會涉及到 內(nèi)容是否是最新的問題, 我們的HTTP請求報文中可以指明這一點(diǎn)
-
目標(biāo): 如果緩沖器中的對象拷貝是最新的, 就不要發(fā)送對象.
-
緩沖器: 在HTTP請求中指定緩存拷貝的日期
If-modified-since: <date>
-
服務(wù)器: 如果緩存拷貝陳舊, 則響應(yīng)報文沒包含對象: HTTP/1.0 304 Not Modified
三、FTP
FTP(File Transfer Protocol), 即 文件傳輸協(xié)議.
- 向遠(yuǎn)程主機(jī)上傳輸文件或者 從遠(yuǎn)程主機(jī)接收文件
- 客戶/服務(wù)器模式
- 客戶端: 發(fā)起傳輸?shù)囊环?/li>
- 服務(wù)器: 遠(yuǎn)程主機(jī)
- ftp: RFC 959
- ftp 服務(wù)器: 端口號為21
如果用過 Xfpt 進(jìn)行 win 和 linux 之間的文件傳輸?shù)脑? 應(yīng)該還是有一點(diǎn)熟悉的.
3.1 FTP: 控制連接與數(shù)據(jù)連接分開
- FTP 客戶端與 FTP服務(wù)器通過端口21聯(lián)系, 并使用TCP為傳輸協(xié)議
- 客戶端通過控制連接獲得身份確認(rèn)
- 客戶端通過控制連接發(fā)送命令瀏覽遠(yuǎn)程目錄
- 收到一個文件傳輸命令時, 服務(wù)器打開一個到客戶端的數(shù)據(jù)連接
- 一個文件傳輸完成后, 服務(wù)器關(guān)閉連接
- 服務(wù)器主動打開第二個TCP數(shù)據(jù)連接用來傳輸另一個文件
- 控制連接: 帶外(“out of bound”) 傳送
- FTP 服務(wù)器維護(hù)用戶的狀態(tài)信息: 當(dāng)前路徑, 用戶賬戶 與 控制連接 對應(yīng) 有狀態(tài)
3.2 FTP 命令, 響應(yīng)
命令樣例
- 在控制連接上以ASCII文本方式傳送
- USER username
- PASS password
- LIST: 請服務(wù)器返回遠(yuǎn)程主機(jī)當(dāng)前目錄的文件列表
- RETR filename: 從遠(yuǎn)程主機(jī)的當(dāng)前目錄檢索文件**(gets)**
- STOP filename: 向遠(yuǎn)程主機(jī)的當(dāng)前目錄存放文件**(puts)**
返回碼樣例
- 狀態(tài)碼和狀態(tài)信息(同HTTP)
- 331 Username OK, password required
- 125 data connection already open; transfer starting
- 425 Can’t open data connection
- 452 Error writing file
四、Email
3個主要組成部分:
- 用戶代理
- 郵件服務(wù)器
- 簡單郵件傳輸協(xié)議:SMTP
用戶代理
- 又名 “郵件閱讀器”
- 撰寫、編輯和閱讀郵件
- 如 Outlook、Foxmail 就是用戶代理
- 輸出和輸入郵件保存在服務(wù)器上
4.1 Email:郵件服務(wù)器
郵件服務(wù)器
- 郵箱中管理和 維護(hù)發(fā)送給用戶的郵件
- 輸出報文隊列 保持待發(fā)送郵件報文
- 郵件服務(wù)器之間的SMTP協(xié)議:發(fā)送email 報文
- 客戶:發(fā)送方郵件服務(wù)器
- 服務(wù)器:接收端郵件服務(wù)器
4.2 Email:SMTP[RFC 2821]
- 使用TCP在客戶端和服務(wù)器之間傳送報文,端口號為25
- 直接傳輸: 從發(fā)送方服務(wù)器到接收方服務(wù)器傳輸?shù)?個階段
- 傳輸?shù)?個階段
- 握手
- 傳輸報文
- 關(guān)閉
- 命令/響應(yīng)交互
- 命令: ASCII文本
- 響應(yīng): 狀態(tài)碼和狀態(tài)信息
- 報文必須為7位ASCII碼
舉例:Alice 給 Bob 發(fā)送報文
- Alice使用用戶代理撰寫郵件 并發(fā)送給 bob@someschool.edu
- Alice的用戶代理將郵件發(fā)送到她的郵件服務(wù)器;郵件放在報文隊列中
- SMTP的客戶端打開到Bob郵件服務(wù)器的TCP連接
- SMTP客戶端通過TCP連接發(fā)送Alice的郵件
- Bob的郵件服務(wù)器將郵件放到Bob的郵箱
- Bob調(diào)用他的用戶代理閱讀郵件
4.3 簡單的SMTP交互
- 客戶的主機(jī)名:crepes.fr
- 服務(wù)器的主機(jī)名:hamburger.edu
- C:開頭的ASCII碼文本行是客戶交給TCP套接字的那些行
- S:開頭的那些行是服務(wù)器發(fā)給TCP套接字的那些行
一旦建立TCP連接,就會進(jìn)行下面過程:
- 客戶從郵件服務(wù)器crepes.fs 向 郵件服務(wù)器 hamburger.edu 發(fā)送了一個報文(Do you like ketchup? How about pickles?)
- HELO, MAIL FROM, RCPT TO, DATA, QUIT 都是一些命令, . 表示結(jié)束
4.4 SMTP 總結(jié)
- SMTP使用持久連接
- SMTP要求報文(首部和主體)為7位ASCII編碼
- SMTP服務(wù)器使用 CRLF.CRLF決定報文的尾部
HTTP比較:
- HTTP: 拉(pull),用戶通過HTTP 拉取信息
- SMTP: 推(push),發(fā)送郵件服務(wù)器把文件推向接收郵件服務(wù)器
- 二者都是ASCII形式的命令/響應(yīng)交互、狀態(tài)碼
- HTTP: 每個對象封裝在各自的響應(yīng)報文中
- SMTP: 多個對象包含在一個報文中
4.5 郵件報文格式
SMTP:交換Email 報文的格式
RFC 822:文本報文的標(biāo)準(zhǔn):
-
首部行:如
-
To:
-
From:
-
Subject:
與SMTP 命令 不同
-
-
主體
- 報文,只能是ASCII碼字符
4.6 報文格式:多媒體擴(kuò)展
如果傳輸?shù)膬?nèi)容不滿足ascii,我們就需要進(jìn)行一些擴(kuò)展。
-
MIME:多媒體郵件擴(kuò)展(multimedia mail extension)
RFC 2045,2056
-
在報文首部用額外的行申明MIME內(nèi)容類型
base64 編碼方式就是 一種 將不滿足 ASCII 的字符 編碼成更長的 字符從而能夠通過SMTP的協(xié)議傳輸
4.7 郵件訪問協(xié)議
- SMTP:傳送到接收方的郵件服務(wù)器
- 郵件訪問協(xié)議:從服務(wù)器訪問郵件
- POP:郵局訪問協(xié)議(Post Office Protocol)[RFC 1939]
- 用戶確認(rèn)(代理 <–> 服務(wù)器)身份并下載
- IMAP:Internet 郵件訪問協(xié)議**(Internet Mail Access Protocol)[RFC 1730]**
- 更多特性(更復(fù)雜)
- 在服務(wù)器上處理存儲的報文
- HTTP:Hotmail,Yahoo!Mail 等
- 方便
- POP:郵局訪問協(xié)議(Post Office Protocol)[RFC 1939]
4.7.1 POP3協(xié)議
事務(wù)處理過程,POP3的用戶代理通常被用戶配置為“下載并刪除” / “下載并保留” 方式。
- 如上面 retr 之后 就 dele 了
- 問題是郵件接收方可能是移動的,在一臺機(jī)器接收后,在其它機(jī)器卻無法訪問,因為用戶報文已經(jīng)被刪除了
下載并保留模式則支持在不同機(jī)器重新讀取郵件,因為郵件仍然保存在郵件服務(wù)器上。
4.7.2 POP3 與 IMAP協(xié)議
POP3:本地管理文件夾
先前的例子使用 **“下載并刪除”**模式。
- 如果改變客戶機(jī),Bob不能閱讀郵件
- “下載并保留”:不同客戶機(jī)上為報文的拷貝
- POP3在會話中是無狀態(tài)的
IMAP :遠(yuǎn)程管理文件夾
- IMAP服務(wù)器將每個報文與一個文件夾聯(lián)系起來
- 允許用戶用目錄來組織報文
- 允許用戶讀取報文組件
- IMAP在會話過程中保留用戶狀態(tài):
- 目錄名、報文ID與目錄名之間映射
五、DNS
5.1 DNS 的必要性
如何標(biāo)記主機(jī)?
- 主機(jī)名(hostname),www.facebook.com 等,但是它們幾乎沒有提供主機(jī)在因特網(wǎng)中的信息
- IP地址,不便于人記憶
- 因而 存在著“字符串”(主機(jī)名)——IP地址的轉(zhuǎn)換的必要性
- 人類用戶提供要訪問機(jī)器的“字符串”名稱
- 由DNS負(fù)責(zé)轉(zhuǎn)換成為二進(jìn)制的網(wǎng)絡(luò)地址
5.2 DNS(domain name system) 系統(tǒng)需要解決的問題?
問題1:如何命名設(shè)備
- 用有意義的字符串:好記,便于人類用使用
- 解決一個平面命名的重名問題:層次化命名
問題2:如何完成名字到IP地址的轉(zhuǎn)換
- 分布式的數(shù)據(jù)庫維護(hù)和響應(yīng)名字查詢
問題3:如何維護(hù):增加或者刪除一個域,需要在域名系統(tǒng)中做哪些工作
5.3 DNS 的歷史
- ARPANET的名字解析解決方案
- 主機(jī)名:沒有層次的一個字符串**(一個平面)**
- 存在著一個(集中)維護(hù)站:維護(hù)著一張主機(jī)名——IP地址的映射文件:Hosts.txt
- 每臺主機(jī)定時從維護(hù)站取文件
- ARPANET解決方案的問題
- 當(dāng)網(wǎng)絡(luò)中主機(jī)數(shù)量很大時
- 沒有層次的主機(jī)名稱很難分配
- 文件的管理、發(fā)布、查找都很麻煩
- 當(dāng)網(wǎng)絡(luò)中主機(jī)數(shù)量很大時
5.4 DNS(Domain Name system)總體思路和目標(biāo)
- DNS的主要思路
- 分層的、基于域的命名機(jī)制
- 若干分布式的數(shù)據(jù)庫完成名字到 IP 地址的轉(zhuǎn)換
- 運(yùn)行在UDP之上端口號為53的應(yīng)用服務(wù)
- 核心的Internet功能,但以應(yīng)用層協(xié)議實現(xiàn)
- 在網(wǎng)絡(luò)邊緣處理復(fù)雜性
- DNS主要目的
- 實現(xiàn)主機(jī)名-IP地址的轉(zhuǎn)換(name/IP translate)
- 其它目的
- 主機(jī)別名到規(guī)范名字的轉(zhuǎn)換:Host aliasing
- 郵件服務(wù)器別名到郵件服務(wù)器的正規(guī)名字的轉(zhuǎn)換:Mail server aliasing
- 負(fù)載均衡:Load Distribution
5.5 問題1:DNS名字空間(The DNS Name Space)
-
DNS域名結(jié)構(gòu)
-
一個層面命名設(shè)備會有很多重名
-
DNDS采用層次樹狀結(jié)構(gòu)的 命名方法
-
Internet 根被劃為幾百個頂級域(top lever domains)
-
通用的(generic)
.com:.edu; .gov; int; .mil; .net; .org
firm:.hsop ; .web ; .arts; .rec ;
-
國家的(countries)
.cn; .us; .nl; .jp
-
-
-
每個(子)域下面可劃分為若干子域(subdomains)**
-
樹葉是主機(jī)
5.5.1 DNS: 根名字服務(wù)器
根DNS服務(wù)器:有400多個根名字服務(wù)器遍及全球,由13個不同的組織分別管理
根名字服務(wù)器提供TLD服務(wù)器的IP地址
5.5.2 DNS 名字空間
-
域名(Domain Name)
- 從本域往上,直到樹根
- 中間使用 “.” 間隔不同的級別
- 例如:ustc.edu.cn
- auto.ustc.edu.cn
- www.auto.ustc.edu.cn
- 域的域名:可以用于表示一個域
- 主機(jī)的域名:一個域上的一個主機(jī)
-
域名的管理
-
一個域管理其下的子域
.jp 被劃分為 ac.jp,co.jp
.cn 被劃分為 edu.cn com.cn
-
創(chuàng)建一個新的域,必須征得它所屬域的同意
-
-
域與物理網(wǎng)絡(luò)無關(guān)
- 域遵從組織界限,而不是物理網(wǎng)絡(luò)
- 一個域的主機(jī)可以不在一個網(wǎng)絡(luò)
- 一個網(wǎng)絡(luò)的主機(jī)不一定在一個域
- 域的劃分是邏輯的,而不是物理的
- 域遵從組織界限,而不是物理網(wǎng)絡(luò)
5.6 問題2:解析問題——名字服務(wù)器(Name Server)
- 一個名字服務(wù)器的問題
- 可靠性問題:單點(diǎn)故障
- 擴(kuò)展性問題:通信容量
- 維護(hù)問題:遠(yuǎn)距離的集中式數(shù)據(jù)庫
- 區(qū)域(zone)
- 區(qū)域的劃分由區(qū)域管理者自己決定
- 將DNS名字空間劃分為互不相交的區(qū)域,每個區(qū)域都是樹的一部分
- 名字服務(wù)器:
- 每個區(qū)域都有一個名字服務(wù)器:維護(hù)著它所管轄區(qū)域的權(quán)威信息(authoritative record)
- 名字服務(wù)器允許被放置在區(qū)域之外,以保障可靠性
5.6.1 名字空間劃分為若干區(qū)域:Zone
權(quán)威DNS服務(wù)器:組織機(jī)構(gòu)的DNS服務(wù)器,提供組織機(jī)構(gòu)服務(wù)器(如Web和mail)可訪問的主機(jī)和IP之間的映射
組織機(jī)構(gòu)可以選擇實現(xiàn)自己維護(hù)或由某個服務(wù)提供商來維護(hù)
5.6.2 TLD 服務(wù)器
頂級域(TLD)服務(wù)器:負(fù)責(zé)頂級域名(如com,org,net,edu和gov)和所有國家級的頂級域名(如cn,uk,fr,ca,jp)
- Network solutions 公司維護(hù) com TLD服務(wù)器
- Educause 公司維護(hù) edu TLD服務(wù)器
5.6.3 區(qū)域名字服務(wù)器維護(hù)資源記錄
- 資源記錄(resource records)
- 作用:維護(hù) 域名-IP地址(其它)的映射關(guān)系
- 位置:Name Server的分布式數(shù)據(jù)庫中
- RR格式:(domain_name,ttl,type,class,Value)
- Domain_name:域名
- Ttl:time to live:生存時間(權(quán)威,緩沖記錄)
- Class 類別:對于Internet,值為IN
- Value 值:可以是數(shù)字,域名或ASCII串
- Type 類別:資源記錄的類型(詳見下面)
DNS 記錄
DNS:保存資源記錄(RR)的分布式數(shù)據(jù)庫
RR格式:(name,value,type,ttl)
name 和 value 取決于 type 的類別
-
Type = A
- name 為主機(jī)
- value 為 IP 地址
-
Type = NS
- name 域名(如foo.com)
- value 為該域名的權(quán)威服務(wù)器的域名
-
Type = CNAME
-
name 為規(guī)范名字的別名
www.ibm.com 的 規(guī)范名字為servereast.backup2.ibm.com
-
value 為規(guī)范名字
-
-
Type = MX
- value 為 name 對應(yīng)的郵件服務(wù)器的名字
TTL:生存時間,決定了資源記錄應(yīng)當(dāng)從緩存中刪除的時間
資源記錄(resource records)的 一個例子:
5.6.4 DNS(Domain Name System)
- DNS 大致工作過程
- 應(yīng)用調(diào)用 解析器(parser)
- 解析器作為客戶 向 Name Server 發(fā)出查詢報文(封裝在UDP段中)
- Name Server 返回響應(yīng)報文(name/ip)
5.6.5 本地名字服務(wù)器(Local Name Server)
- 并不嚴(yán)格屬于層次結(jié)構(gòu)
- 每個ISP(居民區(qū)的ISP、公司、大學(xué))都有一個本地DNS服務(wù)器
- 也稱為"默認(rèn)名字服務(wù)器"
- 當(dāng)一個主機(jī)發(fā)起一個DNS查詢時,查詢被送到其本地DNS服務(wù)器
- 起著代理的作用,將查詢轉(zhuǎn)發(fā)到層次結(jié)構(gòu)中
5.6.6 ★遞歸查詢
- 名字解析過程
- 目標(biāo)名字在 Local Name Server 中
- 情況1:查詢的名字在該區(qū)域內(nèi)部
- 情況2:緩存(cashing)
- 目標(biāo)名字在 Local Name Server 中
當(dāng)與本地名字服務(wù)器不能解析名字時,聯(lián)系根名字服務(wù)器順著根-TLD 一直找到 權(quán)威名字服務(wù)器
- 名字解析負(fù)擔(dān)都放在了當(dāng)前聯(lián)絡(luò)的名字服務(wù)器上
- 問題:根服務(wù)器的負(fù)擔(dān)太重
- 解決:迭代查詢(iterated queries)
5.6.7 迭代查詢
- 主機(jī) cis.poly.edu 想知道 主機(jī) gaia.cs.umass.edu 的IP地址
- 根(及各級域名)服務(wù)器,返回的不是查詢結(jié)果,而是下一個NS的地址
- 最后由權(quán)威名字服務(wù)器給出解析結(jié)果
- 當(dāng)前聯(lián)絡(luò)的服務(wù)器給出可以聯(lián)系的服務(wù)器的名字
- “我不知道這個名字,但可以向這個服務(wù)器請求”
5.6.8 DNS 協(xié)議、報文
DNS 協(xié)議:查詢和響應(yīng)報文的報文格式相同,通過標(biāo)志位來判斷是查詢還是應(yīng)答
5.6.9 提高性能:緩存
- 一旦名字服務(wù)器學(xué)到了一個映射,就將該映射緩存起來
- 根服務(wù)器通常都在本地服務(wù)器中緩存著
- 使得根服務(wù)器不用經(jīng)常被訪問
- 目的:提高效率
- 可能存在的問題:如果情況變化,緩存結(jié)果和權(quán)威資源記錄不一致
- 解決方案:TTL(默認(rèn)2天)
5.7 問題3:維護(hù)問題:新增一個域
-
在上級域的名字服務(wù)器中增加兩條記錄,指向這個新增的子域的域名 和 域名服務(wù)器的地址
-
在新增子域 的名字服務(wù)器上運(yùn)行名字服務(wù)器,負(fù)責(zé)本域的名字解析:名字 -> IP地址
例子:在 com域 中建立一個“Network Utopia”
-
到注冊登記機(jī)構(gòu)注冊域名 networkutopia.com
-
需要向該機(jī)構(gòu)提供權(quán)威DNS服務(wù)器(基本的、和輔助的)的名字和IP地址
-
登記機(jī)構(gòu)在com TLD服務(wù)器中插入兩條RR記錄:
(networkutopia.com,dns1.networkutopia.com,NS)
(dns1.networkutopia.com,212.212.212.1,A)
-
-
在 networkutopia.com 的權(quán)威服務(wù)器中確保有
- 用于Web服務(wù)器的 www.networkuptopia.com 的類型為A的記錄
- 用于郵件服務(wù)器 mail.networkutopia.com 的類型為MX的記錄
5.7.1 攻擊DNS
DDoS 攻擊
-
對根服務(wù)器進(jìn)行流量轟炸
攻擊:發(fā)送大量ping
- 沒有成功
- 原因1:根目錄服務(wù)器配置了流量過濾器,防火墻
- 原因2:Local DNS 服務(wù)器 緩存了TLD服務(wù)器的IP地址,因此無需查詢根服務(wù)器
-
向TLD服務(wù)器流量轟炸攻擊:發(fā)送大量查詢
- 可能更危險
- 效果一般,大部分DNS緩存了TLD
重定向攻擊
-
中間人攻擊
- 截獲查詢,偽造回答,從而攻擊某個(DNS回答指定的IP)站點(diǎn)
-
DNS中毒
- 發(fā)送偽造的應(yīng)答給DNS服務(wù)器,希望它能夠緩存這個虛假的結(jié)果
-
技術(shù)上較困難:分布式截獲和偽造
利用DNS基礎(chǔ)設(shè)施進(jìn)行DDoS
-
偽造某個IP進(jìn)行查詢,攻擊這個目標(biāo)IP
-
查詢放大,響應(yīng)報文比查詢報文大
-
效果有限
總之,DNS 有著很強(qiáng)的健壯性,至今為止,還沒有一個攻擊成功地妨礙了DNS服務(wù)。
因而那些對于13個根服務(wù)器沒有一個在中國的陰謀論在很大程度上是沒必要擔(dān)憂的。
六、P2P應(yīng)用
6.1 純P2P架構(gòu)
- 沒有(或極少)一直運(yùn)行的服務(wù)器
- 任意端系統(tǒng)都可以直接通信
- 利用peer的服務(wù)能力
- Peer節(jié)點(diǎn)間歇上網(wǎng),每次IP地址都有可能變化
例子
- 文件分發(fā)(BitTorrent)
- 流媒體(KanKan)
- VoIP(Skype)
6.2 文件分發(fā):C/S vs P2P
問題:從一臺服務(wù)器分發(fā)文件(大小F)到N個peer需要多少時間
- Peer節(jié)點(diǎn)上下載能力是有限的資源
6.2.1 文件分發(fā)時間:C/S模式
- 服務(wù)器傳輸:都是由服務(wù)器發(fā)送給peer,服務(wù)器必須順序傳輸 (上載) N個文件拷貝:
- 發(fā)送一個copy:F / u
- 發(fā)送N個copy:NF / u
- 客戶端:每個客戶端必須下載一個文件拷貝
- dmin = 客戶端最小的下載速率
- 下載帶寬最小的客戶端下載的時間:F / dmin
采用 C/S 方法將一個F大小的文件分發(fā)給N個客戶端的最小分發(fā)時間:
D C / S ≥ m a x { N F / u s , F / d m i n } D_{C/S} \ge max\{NF / u_s , F/d_{min} \} DC/S?≥max{NF/us?,F/dmin?}
因為 服務(wù)器要發(fā)N份,然后每個客戶端都要下載
隨著N 的增大,最小分發(fā)時間線性增長
6.2.2 文件分發(fā)時間:P2P模式
- 服務(wù)器傳輸:最少需要上載一份拷貝
- 發(fā)送一個拷貝的時間:F/u
- 客戶端:每個客戶端必須下載一個拷貝
- 最小下載帶寬客戶端耗時:F/dmin
- 客戶端:所有客戶端總體下載量NF
- 最大上載帶寬是: u s + Σ u i u_s + \Sigma u_i us?+Σui?
- 除了服務(wù)器可以上載,其他所有的 peer 節(jié)點(diǎn)都可以上載
采用P2P方法發(fā)送一個F大小的文件分發(fā)給N個客戶端耗時:
D P 2 P ≥ m a x ( F / u s , F / d m i n , N F / ( u s + Σ u i ) ) D_{P2P} \ge max(F/u_s, F/d_{min}, NF/(u_s + \Sigma u_i)) DP2P?≥max(F/us?,F/dmin?,NF/(us?+Σui?))
隨著N 的增加,雖然NF增加,但是每個peer節(jié)點(diǎn)也會帶來上載帶寬,因此此時不是隨著N線性增加了
6.2.3 Client-server vs. P2P
$ 客戶端上載速率 = u,F / u = 1小時,u_s = 10u,d_{min} >= u_s $
6.2.4 P2P文件共享
例子
- Alice在其筆記本電腦上運(yùn)行P2P客戶端程序
- 間歇性地連接到 Internet,每次從其ISP得到新的IP地址
- 請求“雙截棍.MP3”
- 應(yīng)用程序顯示其他有 “雙截棍.MP3” 拷貝的對等方
- Alice選擇其中一個對等方,如Bob.
- 文件從 Bob’s PC 傳送到 Alice 的筆記本上:HTTP
- 當(dāng) Alice 下載時,其他用戶也可以從 Alice 處下載
- Alice 的對等方既是一個 Web 客戶端,也是一個瞬時 Web 服務(wù)器
所有的對等方都是服務(wù)器 = 可擴(kuò)展性好!
- 兩大問題:
- 如何定位所需資源
- 如何處理對等方的加入與離開
- 可能的方案
- 集中
- 分散
- 半分散
6.2.5 非結(jié)構(gòu)化P2P
6.2.5.1 P2P:集中式目錄
最初的 “Napster” 設(shè)計
-
當(dāng)對等方連接時,它告知中心服務(wù)器:
TP地址
內(nèi)容
-
Alice 查詢 “雙截棍.MP3”
-
Alice 從 Bob 處請求文件
存在的問題:
- 單點(diǎn)故障
- 性能瓶頸
- 侵犯版權(quán)
文件傳輸是分散的,而定位內(nèi)容則是高度集中的
6.2.5.2 查詢洪泛:Gnutella(完全分布式)
- 全分布式
- 沒有中心服務(wù)器
- 開放文件共享協(xié)議
- 許多Gnutella客戶端實現(xiàn)了Gnutella協(xié)議
- 類似HTTP有許多的瀏覽器
- 覆蓋網(wǎng)絡(luò):圖
- 如果x和y之間有一個TCP連接,則二者之間在一條邊
- 所有活動的對等方和邊就是覆蓋網(wǎng)絡(luò)
- 邊并不是物理鏈路
- 給定一個對等方,通常所連接的節(jié)點(diǎn)少于10個
Gnutella:協(xié)議
- 在已有的TCP連接上發(fā)送查詢報文
- 對等方轉(zhuǎn)發(fā)查詢報文
- 以反方向返回查詢命中報文
我們稱這種查詢方式為 洪泛(flooding)。
顯然我們的查詢會不斷向外擴(kuò)展,當(dāng)規(guī)模太大的時候,壓力很大。
我們可以通過tll(time to live),緩存等手段來改善,但顯然,這種完全分布式的P2P 管理方式較難維護(hù)。
Gnutella:對等方加入
-
對等方 x 必須首先發(fā)現(xiàn)某些已經(jīng)在覆蓋網(wǎng)絡(luò)中的其他對等方:使用可用對等方列表
自己維持一張對等方列表(經(jīng)常開機(jī)的對等方的IP)
聯(lián)系維持列表的 Gnutella 站點(diǎn)
-
x 接著試圖與該列表上的對等方建立 TCP 連接,直到與某個對等方 y 建立連接
-
x 向 y 發(fā)送一個Ping報文,y 轉(zhuǎn)發(fā)該Ping報文
-
所有收到Ping報文的對等方以 Pong報文響應(yīng)
IP地址、共享文件的數(shù)量及總字節(jié)數(shù)
-
x 收到許多Pong報文,然后它能建立其他TCP連接
6.2.5.3 利用不勻稱性:KaZaA(混合體)
- 每個對等方要么是一個組長,要么隸屬于一個組長
- 對等方與其組長之間有TCP連接
- 組長對之間有TCP連接
- 組長跟蹤其所有的孩子的內(nèi)容
- 組長與其他組長聯(lián)系
- 轉(zhuǎn)發(fā)查詢到其他組長
- 獲得其他組長的數(shù)據(jù)拷貝
可見 組長間是 P2P,而組員和組長間是C/S
KaZaA:查詢
- 每個文件有一個散列標(biāo)識碼和一個描述符
- 客戶端向其組長發(fā)送關(guān)鍵字查詢
- 組長用匹配進(jìn)行響應(yīng):
- 對每個匹配:元數(shù)據(jù)、散列標(biāo)識碼和IP地址
- 如果組長將查詢轉(zhuǎn)發(fā)給其他組長,其他組長也以匹配進(jìn)行響應(yīng)
- 客戶端選擇要下載的文件
- 向擁有文件的對等方發(fā)送一個帶散列標(biāo)識碼的 HTTP請求
6.2.5.4 P2P文件分發(fā):BitTorrent
BitTorrent 是一個很常見的東西,我們平時在BT網(wǎng)站下載電影,BT磁力鏈接……
BitTorrent 是一種用于文件分發(fā)的流行P2P協(xié)議。
參與一個特定文件分發(fā)的所有對等方的集合被稱為一個洪流(torrent)。
一個洪流中的對等方彼此下載等長度的文件塊(chunk),典型長度為256KB。
- 文件被分為一個個塊 256KB,而對于是否擁有某個塊,用位圖(bitmap)來維護(hù)
- 網(wǎng)絡(luò)中的這些 peers 發(fā)送接收文件塊,相互服務(wù)
-
Peer 加入 torrent:
- 一開始沒有塊,但是將會通過其他節(jié)點(diǎn)處累積文件塊
- 向**跟蹤服務(wù)器(Tracker)**注冊,獲得 peer 節(jié)點(diǎn)列表,和部分 peer 節(jié)點(diǎn)構(gòu)成鄰居關(guān)系(“連接”)
- 周期性的通知Tracker 自己仍然在洪流中
-
當(dāng)peer下載時,該 peer 可以同時向其他節(jié)點(diǎn)提供上載服務(wù)
-
Peer可能會變換用于交換塊的 peer 節(jié)點(diǎn)
-
擾動churn:peer 節(jié)點(diǎn)可能會上線或者下線
-
一旦一個 peer 擁有整個文件,它會(自私的)離開或者保留(利他主義)在 torrent 中
BitTorrent:請求,發(fā)送文件塊
請求塊:
- 在任何給定時間,不同 peer 節(jié)點(diǎn)擁有一個文件塊的子集
- 周期性的,Alice節(jié)點(diǎn)向鄰居詢問他們擁有哪些塊的信息
- Alice 向 peer 節(jié)點(diǎn)請求它希望的塊,稀缺的塊
發(fā)送塊:一報還一報tit-for-tat
- Alice向 4 個 peer 發(fā)送塊,這些塊向它自己提供最大帶寬的服務(wù),也就是說,向?qū)ψ约汉玫泥従影l(fā)送塊
- 其他 peer 被Alice阻塞(將不會從Alice處獲得服務(wù))
- 每10秒重新評估一次:前4位
- 每個30秒:隨機(jī)選擇其他peer節(jié)點(diǎn),向這個節(jié)點(diǎn)發(fā)送塊
- “優(yōu)化疏通”這個節(jié)點(diǎn)
- 新選擇的節(jié)點(diǎn)可以加入這個top
所以我們平時用的BT是如何工作的呢?
- 用戶在搜索引擎上查詢
- 下載 torrent 文件
- torrent 文件中包含了 tracking server 的信息
- 向 tracking server 發(fā)送請求,然后會返回一個peer列表
- 我們再和這些 peer 進(jìn)行通信
6.2.6 DHT(結(jié)構(gòu)化P2P)
DHT 即 分布式散列表,它是一種簡單的數(shù)據(jù)庫,數(shù)據(jù)庫記錄分布在一個P2P系統(tǒng)的多個對等方上。
每個節(jié)點(diǎn)擁有一個哈希值,然后根據(jù)哈希值的大小,將節(jié)點(diǎn)組成一個有序的拓?fù)洵h(huán)狀結(jié)構(gòu)。
而文件也有哈希值,也按照類似的方法,按照哈希值從小到大將文件分組存放在某個對等方上。
七、CDN
7.1 視頻流化服務(wù)和CDN:上下文
- 視頻流量:占據(jù)著互聯(lián)網(wǎng)大部分的帶寬
- Netflix,YouTube:占據(jù)37%,16%的ISP下行流量。
- ~1B(billion) YouTube 用戶,~75M Netflix用戶
- 挑戰(zhàn):規(guī)模性-如何服務(wù)者~1B 用戶?
- 單個超級服務(wù)器無法提供服務(wù)(為什么)
- 挑戰(zhàn):異構(gòu)性
- 不同用戶擁有不同的能力(例如:有線接入和移動用戶:帶寬豐富和受限用戶)
- 解決方案:分布式的,應(yīng)用層面的基礎(chǔ)設(shè)施
7.2 多媒體:視頻
- 視頻:固定速度顯示的圖像序列
- e.g.24 images/sec
- 網(wǎng)絡(luò)視頻特點(diǎn):
- 高碼率:>10x于音頻,高的網(wǎng)絡(luò)帶寬需求
- 可以被壓縮
- 90%以上的網(wǎng)絡(luò)流量是視頻
- 數(shù)字化圖像:像素的陣列
- 每個像素被若干bits表示
- 編碼:使用圖像內(nèi)和圖像間的冗余來降低編碼的比特數(shù)
- 空間冗余(圖像內(nèi))
- 時間冗余(相鄰的圖像間)
- **CBR:(constant bitrate):**以固定速率編碼
- **VBR:(variable bitrate):**視頻編碼速率隨時間的變化而變化
- 例子:
- MPEG1 (CD-ROM) 1.5Mbps
- MPEG2 (DVD) 3-6 Mbps
- MPEG4 (often used in Internet,< 1 Mbps)
下面是空間編碼和時間編碼的例子:
7.3 存儲視頻的流化服務(wù)
簡單場景:
我們在看視頻的方式難道要把視頻全部下載下來再看嗎?
事實上,我們是通過流化服務(wù),邊下邊看。
7.3.1 多媒體流化服務(wù):DASH
- DASH:Dynamic,Adaptive Streaming over HTTP
- 服務(wù)器:
- 將視頻文件分割成多個塊
- 每個塊獨(dú)立存儲,編碼于不同碼率(8-10種)
- 告示文件(manifest file):提供不同塊的URL
- 客戶端:
- 先獲取告示文件
- 周期性地測量服務(wù)器到客戶端的帶寬
- 查詢告示文件,在一個時刻請求一個塊,HTTP頭部指定字節(jié)范圍
- 如果帶寬足夠,選擇最大碼率的視頻塊
- 會話中的不同時刻,可以切換請求不同的編碼塊(取決于當(dāng)時的可用帶寬)
7.3.2 流式多媒體技術(shù)3:DASH
- “智能”客戶端:客戶端自適應(yīng)決定
- 什么時候去請求塊(不至于緩存挨餓,或者溢出)
- 請求什么編碼速率的視頻塊(當(dāng)帶寬夠用時,請求高質(zhì)量的視頻塊)
- 哪里去請求塊(可以向離自己近的服務(wù)器發(fā)送URL,或者向高可用帶寬的服務(wù)器請求)
7.4 內(nèi)容分發(fā)網(wǎng)(Content Distribution Networks)
- 挑戰(zhàn):服務(wù)器如何通過網(wǎng)絡(luò)向上百萬用戶同時流化視頻內(nèi)容(上百萬視頻內(nèi)容)?
- 選擇1:單個的、大的超級服務(wù)中心“mega-server”
- 服務(wù)器到客戶端路徑上跳數(shù)較多,瓶頸鏈路的帶寬小導(dǎo)致停頓
- “二八規(guī)律”決定了網(wǎng)絡(luò)同時充斥著同一個視頻的 多個拷貝,效率低(付費(fèi)高、帶寬浪費(fèi)、效果差)
- 單點(diǎn)故障點(diǎn),性能瓶頸
- 周邊網(wǎng)絡(luò)的擁塞
評述:相當(dāng)簡單,但是這個方法不可擴(kuò)展
-
選擇2:通過CDN,全網(wǎng)部署緩存節(jié)點(diǎn),存儲服務(wù)內(nèi)容,就近為用戶提供服務(wù),提高用戶體驗
- enter deep:將CDN服務(wù)器深入到許多接入網(wǎng)
- 更接近用戶,數(shù)量多,離用戶近,管理困難
- Akamai, 1700個位置
- bring home:部署在少數(shù)(10個左右)關(guān)鍵位置,如將服務(wù)器簇安裝于POP附近(離若干1st ISP POP較近)
- 采用租用線路將服務(wù)器簇連接起來
- Limelight
- enter deep:將CDN服務(wù)器深入到許多接入網(wǎng)
-
CDN:在 CDN 節(jié)點(diǎn)中存儲內(nèi)容的多個拷貝,讓內(nèi)容靠近用戶
- e.g. Netflix stores copies of MadMen
-
用戶從CDN中請求內(nèi)容
- 重定向到最近的拷貝,請求內(nèi)容
- 如果網(wǎng)絡(luò)路徑擁塞,可能選擇不同的拷貝
- OTT 挑戰(zhàn):在擁塞的互聯(lián)網(wǎng)上復(fù)制內(nèi)容
- 從哪個CDN節(jié)點(diǎn)中獲取內(nèi)容?
- 用戶在網(wǎng)絡(luò)擁塞時的行為?
- 在哪些CDN節(jié)點(diǎn)中存儲什么內(nèi)容?
CDN:“簡單”內(nèi)容訪問場景
Bob(客戶端)請求視頻http://netcinema.com/6Y7B23V
- 視頻存儲在CDN,位于http://KingCDN.com/NetC6y&B23V
大致過程就是:主機(jī)訪問本地DNS服務(wù)器,然后做了一個迭代查詢,最終一直到CDN權(quán)威服務(wù)器,然后由KingCDN內(nèi)容分發(fā)服務(wù)器將內(nèi)容發(fā)送到主機(jī)
案例學(xué)習(xí):Netflix
- Netflix 維護(hù)了一個賬戶注冊的服務(wù)器
- 然后租了 Amazon 的云服務(wù)器,視頻制作在 云服務(wù)器上進(jìn)行視頻制作,網(wǎng)頁也放在了云服務(wù)器上
- 制作完成后上傳到CDN
- 用戶完成賬戶注冊后,點(diǎn)擊鏈接重定向進(jìn)行重定向,然后獲得了緩存節(jié)點(diǎn)
- 用戶可以去選擇一個CDN 緩存節(jié)點(diǎn)也可以自動分配
- 然后從CDN緩存節(jié)點(diǎn)獲得 流化服務(wù)
八、TCP/IP Socket編程快速入門
大黑書上接著就開始講套接字編程了,想著還是實踐下比較好,所以這里寫一下怎樣通過 Python 使用 Socket
先回顧一下:
socket 是一套用于不同主機(jī)間通信的 API,工作在 TCP/IP 協(xié)議棧之上
我們的瀏覽器,App,ssh客戶端都是基于 socket 來實現(xiàn)的
為了進(jìn)行主機(jī)間的通信,我們需要指明 IP地址 和 端口號,IP地址很好理解,而 端口號主要為了 OS 區(qū)分?jǐn)?shù)據(jù)發(fā)送到哪個應(yīng)用上
TCP 是可靠數(shù)據(jù)傳輸,我們發(fā)送數(shù)據(jù)對方一定能收到。
TCP 要求 數(shù)據(jù)收發(fā)雙方扮演不同角色:服務(wù)器和客戶端,服務(wù)器等待客戶端連接
下面就在 Pycharm 上進(jìn)行一個簡單的體驗
8.1 創(chuàng)建簡單服務(wù)器
這個服務(wù)器只需將收到的消息原封不動地發(fā)回去
import socketwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind(("0.0.0.0", 1234))s.listen()c, addr = s.accept()with c:print(addr, "connected.")while True:data = c.recv(1024)if not data:breakc.sendall(data)
with 是語法糖,語句塊結(jié)束,自動調(diào)用 s.close()
下面是 socket 的構(gòu)造函數(shù):
def __init__(self, family=-1, type=-1, proto=-1, fileno=None):
我們傳入的 AF_INET 指明了家族(family) 是 IPv4 的地址家族(address family)
SOCK_STREAM 則指明我們用的是 TCP 協(xié)議,對應(yīng)的是type 協(xié)議,STREAM其實代表了 TCP 是一個流式協(xié)議,我們會在后面的章節(jié)中學(xué)到
然后通過 bind() 函數(shù)將我們創(chuàng)建的socket 關(guān)聯(lián)到主機(jī)的某一個網(wǎng)卡(又:網(wǎng)路接口/network interface)和 端口 上
”0.0.0.0“ 這里單純代表主機(jī)上任意一個網(wǎng)卡都可以使用這個 socket 進(jìn)行通信
listen 則將 socket 置為監(jiān)聽狀態(tài),并等待客戶端連接
accept 則會返回一個新的socket (上面的 c )和 IP地址(上面的 addr)
我們 在 WSL 中,通過netcat(linux 下可以用來讀寫 TCP/UDP 數(shù)據(jù)的命令行工具,以 本地ip 作為回送地址,連接端口號1234
結(jié)果:
8.2 客戶端
客戶端向服務(wù)器請求連接,然后發(fā)送數(shù)據(jù)并接收服務(wù)器返回的數(shù)據(jù)并打印
import socketwith socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.connect(("127.0.0.1", 1234))s.sendall(b"Hello, world!")data = s.recv(1024)print(f"Received: {data}")
結(jié)果:
8.3 并發(fā)多客戶端通信
TCP是一個四元組,天生支持我們區(qū)分多客戶端對于同一端口或者不同端口的訪問,我們自然可以實現(xiàn)并發(fā)多客戶端通信
對于 具體到哪個進(jìn)程,可以由Pid 區(qū)分,這就是 OS的事情了
8.3.1 多線程的Socket 服務(wù)器
我們前面的服務(wù)器一次只能和一個客戶端通信,對于并發(fā)多客戶端通信,我們這里采用最簡單的方式:多線程
import socket
import threadingdef handle_client(c, addr):print(addr, 'connected.')while True:data = c.recv(1024)if not data:breakc.sendall(data)with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind(("0.0.0.0", 1234))s.listen()while True:c, addr = s.accept()t = threading.Thread(target=handle_client, args=(c, addr))t.start()
- 循環(huán)等待連接
- 然后將 新開線程去進(jìn)行通信
結(jié)果:
但是由于 Python GIL(Global Interpreter Lock)的存在,Python 中的線程做不到真正的并發(fā),而且線程本身也會占用額外的系統(tǒng)資源
除了線程外,我們還可以使用基于事件驅(qū)動的 selectors 來實現(xiàn)多個連接的并發(fā),或者通過更高層的 asyncio 來實現(xiàn)異步的 socket 代碼。
這里不再介紹
8.4 簡易HTTP服務(wù)器
那么 HTTP 服務(wù)器是如何實現(xiàn)的呢?
HTTP 是 TCP 協(xié)議的典型應(yīng)用,也是 瀏覽器和 服務(wù)器交互的主要方式
服務(wù)器通常監(jiān)聽80端口,然后等待客戶端連接
前面我們也介紹了,客戶端發(fā)送請求報文,服務(wù)發(fā)送響應(yīng)報文
我們隨便寫一個 html 的頁面,然后存到我們的工作目錄下
- 主函數(shù)體我們切換下工作目錄
- 然后和前面一樣,死循環(huán)監(jiān)聽
if __name__ == "__main__":# Change working directory to script folderos.chdir(os.path.dirname(os.path.abspath(__file__)))with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:s.bind(("0.0.0.0", 1234))s.listen()while True:c, addr = s.accept()t = threading.Thread(target=handle_client, args=(c, addr))t.start()
服務(wù)邏輯:
- 接收 http 頭部
- 如果沒有指定文件,我們就重定向到 之前寫的html文件
- 嘗試打開目標(biāo)文件,讀取內(nèi)容
- 返回內(nèi)容
- 如果文件不存在,返回404
def handle_client(c, addr):print(addr, 'connected.')with c:request = c.recv(1024)# parse HTTP headersheaders = request.split(b"\r\n")file = headers[0].split()[1].decode()# Load file contentif file == "/":file = "/index.html"try:with open(WEBROOT + file, "rb") as f:content = f.read()response = b"HTTP/1.0 200 OK\r\n\r\n" + contentexcept FileNotFoundError:response = b"HTTP/1.0 404 NOT FOUND\r\n\r\nFile not found!"# Send HTTP responsec.sendall(response)
我們可以在瀏覽器內(nèi)輸入服務(wù)器 IP地址 + 端口號來發(fā)送請求
結(jié)果:
如果我們指定了一個不存在的文件:
九、TCP 套接字編程
通過 P8,大致了解了服務(wù)器和客戶端之間是如何通過 Sokcet 來傳輸報文的。下面進(jìn)入大黑書關(guān)于這一部分的內(nèi)容。
9.1 Socket 編程
應(yīng)用進(jìn)程使用傳輸層提供的服務(wù)才能夠交換報文,實現(xiàn)應(yīng)用協(xié)議,實現(xiàn)應(yīng)用
- TCP / IP:應(yīng)用進(jìn)程使用Socket API 訪問傳輸服務(wù)
- 地點(diǎn):界面上的SAP(Socket)方式:Socket API
目標(biāo)“:學(xué)習(xí)如何構(gòu)建能借助 socket 進(jìn)行通信的 C/S 應(yīng)用程序
socket:分布式應(yīng)用進(jìn)程之間的門,傳輸層協(xié)議提供的端到端服務(wù)接口
2種傳輸層服務(wù)的socket類型:
- TCP:可靠的、字節(jié)流的服務(wù)
- UDP:不可靠(數(shù)據(jù)UDP數(shù)據(jù)包)服務(wù)
9.2 TCP套接字編程
套接字:應(yīng)用進(jìn)程與端到端傳輸協(xié)議(TCP或UDP)之間 的門戶
TCP服務(wù):從一個進(jìn)程向另一個進(jìn)程可靠地傳輸字節(jié)流
服務(wù)器首先運(yùn)行,等待連接建立
1.服務(wù)器進(jìn)程必須先處于運(yùn)行狀態(tài)
- 創(chuàng)建歡迎socket
- 和本地端口捆綁(bind)
- 在歡迎socket 上阻塞式等待接收用戶的連接
客戶端主動和服務(wù)器建立連接:
- 創(chuàng)建客戶端本地套接字(隱式捆綁到本地)
- 指定服務(wù)器進(jìn)程的IP地址和端口號,與服務(wù)器進(jìn)程連接
- 當(dāng)與客戶端連接請求到來時
- 服務(wù)器**接受(accept)**來自用戶端的請求,解除阻塞式等地,返回一個新的sokcet(與歡迎 socket 不一樣),與客戶端通信
- 允許服務(wù)器與多個服務(wù)器通信
- 使用源IP和源端口來區(qū)分不同的客戶端
- 服務(wù)器**接受(accept)**來自用戶端的請求,解除阻塞式等地,返回一個新的sokcet(與歡迎 socket 不一樣),與客戶端通信
- 連接API調(diào)用有效時,客戶端 P 與 服務(wù)器建立了TCP連接
從應(yīng)用程序的角度
TCP在客戶端和服務(wù)器進(jìn)程之間 提供了可靠的、字節(jié)流(管道)服務(wù)
C/S模式的應(yīng)用樣例:
- 客戶端從標(biāo)準(zhǔn)輸入裝置 讀取一行字符,發(fā)送給服務(wù)器
- 服務(wù)器從 socket 讀取字符
- 服務(wù)器將字符轉(zhuǎn)換成大寫,然后返回給客戶端
- 客戶端從socket中讀取一行字符,然后打印出來
實際上,這里描述了C-S之間交互的動作次序
下面這個交互過程的例圖其實就和我們前面寫的python程序差不多
9.3 數(shù)據(jù)結(jié)構(gòu) sockaddr_in
IP 地址和 port 捆綁關(guān)系的數(shù)據(jù)結(jié)構(gòu)(標(biāo)示進(jìn)程的端節(jié)點(diǎn))
這個和 python 中的命名很類似,意義不再贅述
struct sockaddr_in{short sin_family; // AF_INTEu_short sin_port; // portstruct in_addr sin_addr; // IP address, unsigned longchar sin_zero[8]; // align
};
9.4 數(shù)據(jù)結(jié)構(gòu) hostent
域名和IP地址的數(shù)據(jù)結(jié)構(gòu)
struct hostent {char *h_name;char **h_aliases; // 域名別名int h_addrtype;int h_length; // 地址長度char **h_addr_list; // IP 地址列表#define h_addr h_addr_list[0]; // 解析后的IP地址
};
hostent 作為調(diào)用域名解析函數(shù)時的參數(shù),返回后,將 IP 地址拷貝到 socketaddr_in 的 IP 地址部分
9.5 例子:C客戶端(TCP)
- sockaddr:存 服務(wù)器 IP 和 相應(yīng)端口號
- clientSocket:客戶端 socket,就是一個整數(shù)
- prth:指向一個 hostent 對象的指針
- Sentence / modifiedSentence:
- host:服務(wù)器域名
- port:端口號(atoi:ascii to int,即str to int)
- 然后創(chuàng)建 socket:指定地址族PF_INET,SOCK_STREAM等
- 清空sad,然后對其賦值
- 通過host 來初始化 ptrh(hostname to IP address)
- 拿到ptrh后,把IP放到 sad內(nèi)
- 然后建立連接
整個過程:
9.6 例子:C服務(wù)器(TCP)
- sad:服務(wù)器 IP 及 port
- cad:客戶端 IP 及 port
- welcomeSocket / connectionSocket:歡迎socket 和 建立連接后的新socket
- ptrh:和前面類似
- port:端口號
- 初始化welcomeSocket
- 然后清空sad,對其初始化(本地 IP,Port)
- 進(jìn)行 bind(IP,Port)
- 然后 阻塞,等待連接
- accept,建立 connectionSocket
- 讀 報文 到 clientSentence
- 將 capitalizedSentence 寫回
- 關(guān)閉 socket
當(dāng)然,這個邏輯每次只能進(jìn)行一個客戶端的通信,并發(fā)通信的方式自行了解
十、UDP 套接字編程
UDP:在客戶端和服務(wù)器之間 沒有連接
- 沒有握手
- 發(fā)送端在每一個報文中明確地指定目標(biāo)的IP地址和端口號
- 服務(wù)器必須從收到的分組中提取出發(fā)送端的IP地址和端口號
UDP:傳送的數(shù)據(jù)可能亂序,也可能丟失
進(jìn)程視角看UDP服務(wù)
UDP 為客戶端和服務(wù)器提供不可靠的字節(jié)組的傳送服務(wù)
10.1 Client/server socket 交互:UDP
- 服務(wù)器創(chuàng)建socket,然后進(jìn)行bind
- 和 TCP 不同的是,這里沒有了connect 步驟
- Client 直接發(fā)送數(shù)據(jù)報
- 服務(wù)器讀請求
- 服務(wù)器應(yīng)答
- 客戶端讀應(yīng)答
10.2 樣例:C客戶端(UDP)
流程描述:
1.3 樣例:C服務(wù)器(UDP)
流程描述: