計算機網路自頂向下方法第二章學習筆記
應用層(報文)
1、應用層協議原理
應用程式體系結構:
(1)客戶-伺服器體系結構:有一個總是開啟的主機稱為伺服器,服務於其他稱為客戶的主機的請求。
(2)P2P體系結構:應用程式在間斷連線的主機對之間使用直接通訊。自擴充套件性,每個主機可以向其他對等方分發檔案為系統增加服務能力。
程序通過套接字的軟體介面傳送和接收報文。套接字可以看做同一主機內應用層和運輸層的介面。
為了標識接收程序,需要定義兩種資訊:主機的地址(IP地址);目標主機接收程序的識別符號(埠號)
可供應用程式使用的運輸服務:可靠資料傳輸、吞吐量、定時、安全性
應用層協議定義了執行在不同端系統上的應用程式程序如何相互傳遞報文,定義了:交換的報文型別、各種報文型別的語法、欄位的語義、一個程序何時以及如何傳送報文。
2、Web和HTTP
2.1 HTTP概況
Web的應用層協議為超文字傳輸協議(HTTP),由兩個程式實現:客戶程式和伺服器程式。
Web頁面由物件組成,一個物件可以為檔案、圖形、小程式等,通過URL地址定址。多數Web頁面有一個HTML基本檔案以及幾個引用物件。HTML基本檔案通過物件的URL地址引用頁面中的其他物件。URL地址分為兩部分:存放物件的伺服器主機名和物件的路徑名。例如:URL地址http://www.someSchool.edu/someDepartment/picture.gif中www.someSchool.edu為主機名,後面為路徑名。
HTTP定義了Web客戶向Web伺服器請求頁面的方式,以及伺服器向客戶傳送頁面的方式。
2.2 非持續連線和持續連線
(1)非持續連線:在客戶和伺服器長時間範圍內通訊時,每個請求/響應對經單獨的TCP連線傳送
每個TCP連線只傳輸一個請求報文和一個響應報文。因此一次請求Web頁面往往要產生多個TCP連線。
缺點:必須為每個請求的物件建立和維護一個全新的連線;每個物件要經受兩倍RTT的交付時延,一個RTT用於建立TCP,一個傳輸。
(2)持續連線:所有請求/響應對經相同的TCP連線傳送。HTTP預設使用持續連線。
2.3 HTTP報文格式
HTTP請求報文:實體主體在方法為post等才有用,用於關鍵字搜尋等。但GET方法可以將使用者的輸入放在URL中實現關鍵字檢索。例如
例如:
GET /somedir/page.html HTTP/1.1 請求行:方法欄位(GET、POST、HEAD、PUT、DELETE)、URL欄位、HTTP版本欄位
Host: www.someschool.edu 首部行:表明物件所在主機
Connection:close 首部行:表明希望伺服器發完一個報文斷開TCP
HTTP響應報文:
狀態碼有:200 OK(請求成功);301 Moved Permanently(請求的物件已被轉移,新的URL在Location首部行中);400 Bad Request(該請求不能被伺服器理解);404 Not Found(請求的文件不在伺服器上);505 HTTP Version Not Supported。
例如:
HTTP/1.1 200 OK 狀態行:協議版本欄位、狀態碼和相應狀態資訊
Connection:close 首部號:
Date:Tue,0.9 Aug 2011 15:44:04 GMT 首部號:傳送時間
2.4 使用者與伺服器互動:cookie
HTTP伺服器是無狀態的,即不標識使用者。但如果一個web站點希望可以識別使用者,HTTP通過cookie實現。
cookie技術元件:(1)HTTP響應報文中的cookie首部行(2)HTTP請求報文中的cookie首部行(3)使用者端系統中保留一個cookie檔案,由使用者瀏覽器進行管理(4)位於Web站點的一個後端資料庫。
從而服務端可以通過cookie跟蹤使用者,然後進行推薦等操作。
2.5 Web快取
web快取器是能夠代表初始Web伺服器來滿足HTTP請求的網路實體。有自己的磁碟儲存空間,並在儲存空間中儲存最近請求過的物件的副本。
假設瀏覽器請求物件http://www.someschool.edu/campus.gif,會發生如下情況:
(1)瀏覽器建立一個到web快取器的TCP連線,並向web快取器中的物件傳送一個HTTP請求
(2)快取器進行檢查,如果有該物件副本則通過HTTP響應報文回傳。若沒有該物件,就向初始伺服器(www.someschool.edu)請求該物件。
(3)快取器收到初始伺服器的HTTP響應報文後,在本地儲存空間儲存一份副本,然後向客戶的瀏覽器回傳該副本。
Web快取器的優勢:可以大大減少對客戶請求的響應時間;可以減小因特網上的web流量,從而改善所有應用的效能。
2.6 條件GET方法
web快取器存在一個問題:儲存在該快取器中的副本可能是陳舊的。可以通過條件GET方法來證實快取器的副本是最新的。
條件GET方法:(1)使用get方法(2)請求報文中包含If-Modified-Since: ,代表上次修改的日期。通過最後修改日期來區分是否為最新的內容。
3 檔案傳輸協議:FTP
FTP和HTTP都是文字傳輸協議,但也有一些重要的區別:(1)FTP使用兩個並行的TCP連線來傳輸檔案,一個是控制連線,一個是資料連線。控制連線用於兩主機間傳輸控制資訊,如使用者標識、口令等。資料連線用於傳送檔案。因此FTP使用兩個埠:20和21埠。
當用戶主機與遠端主機開始一個FTP會話時,FTP的客戶端首先在伺服器21埠與伺服器發起控制TCP連線,併發送使用者標識等資訊。當服務端從控制連線上收到檔案傳輸命令後,就發起TCP資料連線,傳輸完畢後關閉。在同一會話中,若客戶端來需要傳輸資料,則開啟新的資料連線。因此FTP的控制連線會貫穿整個使用者會話,資料鏈接只在檔案傳輸時建立。
FTP伺服器必須在整個會話期間保留使用者狀態,需要追蹤使用者在遠端目錄樹上的位置,從而限制了FTP維持的會話總數。
FTP命令和回答:
USER username:使用者標識 PASS password:使用者口令 LIST:用於向伺服器請求所有檔案列表,通過資料連線傳送
RETR filename:從伺服器get檔案 STOR filename:向伺服器put檔案
4 因特網的電子郵件
因特網電子郵件系統組成:使用者代理、郵件伺服器、簡單郵件傳輸協議(SMTP)。
4.1 SMTP
SMTP用於從傳送方的郵件伺服器傳送報文到接收方的郵件伺服器。TCP連線
與HTTP的比較:HTTP是一個拉協議,主要從伺服器拉取資訊,FTP是推協議。SMTP要求每個報文使用7位元ASCII碼格式,對於影象檔案等需要轉換。SMTP將文字和圖形等檔案放在一個報文中,而HTTP每個物件放在不同報文中。
4.2 郵件報文格式
每個首部必須含有一個From:首部行和一個To:首部行;也許有Subject:首部行以及其他可選的首部行。
4.3 郵件訪問協議
假設A向B發郵件,郵件訪問協議將B郵件伺服器上的報文傳送給B的主機。包括第三版郵局協議(POP3)、因特網郵件訪問協議(IMAP)以及HTTP。而SMTP是將郵件從A的使用者代理傳輸到B的郵件伺服器。
POP3:比較簡單的郵件範文協議。按三個階段工作:特許、事物處理以及更新。第一階段通過使用者名稱和口令鑑別使用者;第二階段使用者取回報文等操作;第三階段退出,郵件伺服器會刪除那些被標記為刪除的報文。
IMAP:POP3協議只在本地維持郵件的資料夾,不提供任何建立遠端資料夾併為報文指派資料夾的方法。而IMAP伺服器把每個報文與一個資料夾聯絡起來,為使用者提供建立資料夾以及將郵件從一個資料夾移動到另一個資料夾的命令,允許使用者代理獲取報文元件的命令。
HTTP:當你使用瀏覽器收發郵件時,從使用者到郵件伺服器之間用HTTP傳輸。
5 DNS:因特網目錄服務
主機的一種標識方法是用其主機名,例如:cnn.com、www.yahoo.com等。然而該主機名很難被機器辨識,因此用IP地址來標識。
5.1 DNS提供的服務(53號埠)
域名系統(DNS)是將主機名轉換為IP地址的目錄服務。DNS是:(1)一個由分層的DNS伺服器實現的分散式資料庫(2)一個使得主機能夠查詢分散式資料庫的應用層協議。
DNS通常由其他應用層協議所使用,假如瀏覽器要訪問URL www.someschool.edu/index.html,做法如下:使用者主機上執行著DNS應用的客戶端;瀏覽器將URL中抽取出主機名www.someschool.edu,並將這臺主機名傳給DNS應用的客戶端;DNS客戶向DNS伺服器傳送一個包含主機名的請求;DNS客戶最終會收到一個回答報文,並得到主機名的IP地址;瀏覽器向該IP地址80埠的HTTP伺服器程序發起一個請求。
DNS提供的其他服務:
主機別名:有著複雜主機名的主機能擁有一個或者多個別名。
郵件伺服器別名:便於記憶的電子郵件別名。
負載分配:DNS可以用於冗餘伺服器之間進行負載分配。單個站點會有多臺伺服器,DNS資料中心會儲存這些IP地址集合,因此多個伺服器可以有相同的別名。
5.2 DNS工作機理
DNS採用分散式的設計方案。
(1)分散式、層次資料庫
DNS使用大量DNS伺服器,以層次方式組織,分為3中型別:根DNS伺服器、頂級域(TLD)DNS伺服器、權威DNS伺服器。
根DNS伺服器:全球一共13個根DNS伺服器。規定了合法域名.com .net .org等
頂級域伺服器:負責維護頂級域名如com、org以及所有國家頂級域名cn、uk等
權威DNS伺服器:在因特網上具有公共可訪問主機(web伺服器)的每個組織機構必須提供公共可訪問的DNS記錄,這些記錄將這些主機名對映為IP地址。多數大學和大公司都實現或維護其權威DNS伺服器。
本地DNS伺服器:嚴格來說並不屬於DNS伺服器的層次結構,每個ISP都有一臺本地DNS伺服器。
以訪問www.amazon.com為例,客戶首先本地伺服器聯絡,本地伺服器會與根伺服器聯絡,將返回頂級域名com的TLD伺服器的IP地址。然後本地伺服器與這些TLD伺服器之一聯絡,將為amazon.com返回權威伺服器的IP地址。然後,本地伺服器與權威伺服器聯絡,它為www.amazon.com返回IP地址。最後,本地伺服器將該IP返回給客戶。注意到該過程有4份查詢報文和4份回答報文,可以通過DNS快取解決。
(2)DNS快取
為了改善時延效能並減少在因特網上傳輸的DNS報文數量,DNS使用快取技術。通常在本地伺服器實現,可以快取主機名/IP地址對,可以快取TLD伺服器地址,從而繞過根DNS伺服器。
5.3 DNS記錄和報文
資源記錄是一個4元組:(Name,Value,Type,TTL)
TTL為該記錄的生存時間,決定了資源記錄應當從快取中刪除的時間。
Type=A,則Name是主機名,Value是該主機名對應的IP地址。
Type=NS,則Name是域,Value是如何獲取該域中主機IP地址的權威DNS伺服器的主機名。
Type=CNAME,則Value是別名為Name的主機對應的規範主機名。
Type=MX,則Value是別名為Name的郵件伺服器對應的規範主機名。從而使得同一公司的郵件伺服器和web伺服器可以使用相同別名。
6 套接字程式設計
UDP套接字程式設計:
功能:客戶從鍵盤讀入一行字元,發給服務端,服務端將其轉成大寫返回給客戶端
UDPClient.py
from socket import *
serverName = "127.0.0.1"
serverPort = 10021
clientSocket = socket(AF_INET,SOCK_DGRAM)
while True:
message = raw_input('Input lowercase sentence:')
if message=='quit':
break
clientSocket.sendto(message,(serverName,serverPort))
modifiedMessage,serverAddress = clientSocket.recvfrom(2048)
print modifiedMessage
clientSocket.close()
AF_INET表示底層為IPv4,SOCK_DGRAM表示其為UDP套接字
UDPServer.py
from socket import *
serverName = "127.0.0.1"
serverPort = 10021
serverSocket = socket(AF_INET,SOCK_DGRAM)
serverSocket.bind((serverName,serverPort))
print ("The server is ready to receive")
while True:
message,clientAddress = serverSocket.recvfrom(2048)
modifiedMessage = message.upper()
serverSocket.sendto(modifiedMessage,clientAddress)
TCP套接字程式設計:
TCPClient.py
from socket import *
serverName = "127.0.0.1"
serverPort = 10021
clientSocket = socket(AF_INET,SOCK_STREAM)
clientSocket.connect((serverName,serverPort))
while True:
message = raw_input('Input lowercase sentence:')
if message=='quit':
break
clientSocket.send(message)
modifiedMessage,serverAddress = clientSocket.recvfrom(2048)
print modifiedMessage
clientSocket.close()
TCPServer.py
from socket import *
serverName = "127.0.0.1"
serverPort = 10021
serverSocket = socket(AF_INET,SOCK_STREAM)
serverSocket.bind((serverName,serverPort))
serverSocket.listen(1)
print ("The server is ready to receive")
while True:
connectionSocket,addr = serverSocket.accept()
message = connectionSocket.recv(2048)
modifiedMessage = message.upper()
connectionSocket.send(modifiedMessage)
connectionSocket.close()