標籤:iperf
Iperf 版本建議採用linux版本,事實上,windows版也很好用。Iperf 是一個 TCP/IP 和 UDP/IP 的效能測量工具,通過調諧各種參數可以測試TCP的最大頻寬,並報告頻寬、延遲,最大段和傳輸單元最大值大小等統計資訊。Iperf可以運行於Linux/BSD、Unix及Windows等作業系統。
頻寬測試通常採用UDP模式,因為能測出極限頻寬、時延抖動、丟包率。在進行測試時,首先以鏈路理論頻寬作為資料發送速率進行測試,例如,從用戶端到伺服器之間的鏈路的理論頻寬為100Mbps,先用 -b 100M進行測試,然後根據測試結果(包括實際頻寬,時延抖動和丟包率),再以實際頻寬作為資料發送速率進行測試,會發現時延抖動和丟包率比第一次好很多,重複測試幾次,就能得出穩定的實際頻寬。
1、UDP 模式
伺服器端 iperf -u -s
用戶端
iperf -u -c 192.168.1.1 -b 100M -t 60
在udp模式下,以100Mbps為資料發送速率,用戶端到伺服器192.168.1.1上傳頻寬測試,測試時間為60秒。
iperf -u -c 192.168.1.1 -b 5M -P 30 -t 60
用戶端同時向伺服器端發起30個連接線程,以5Mbps為資料發送速率。
iperf -u -c 192.168.1.1 -b 100M -d -t 60
以100M為資料發送速率,進行上下行頻寬測試。
2、TCP模式
伺服器端 iperf -s
用戶端
iperf -c 192.168.1.1 -t 60
在tcp模式下,用戶端到伺服器192.168.1.1上傳頻寬測試,測試時間為60秒。
iperf -c 192.168.1.1 -P 30 -t 60
用戶端同時向伺服器端發起30個連接線程。
iperf -c 192.168.1.1 -d -t 60
進行上下行頻寬測試。
另外,
-p 監聽或者串連的連接埠號碼
-w TCP滑動視窗的大小
3、Iperf工作原理
Iperf主要的功能是測試基於特定路徑的TCP串連的效能,我們知道TCP串連調整最基本的措施是調整TCP視窗的大小,視窗大小控制在任何節點網路中可以存在的資料大小。如果該值太小,寄件者將會在某段時間處於空閑狀態,從而影響發送的效能。TCP視窗大小的理論值為鏈路瓶頸頻寬與往返時延的乘積:
TCP_Window=Bottleneck_Bandwidth*Round_Trip_Time
例如鏈路瓶頸頻寬為45Mbps,往返時延為42ms(可以通過ping來測試),那麼視窗的理論值為:
45Mbps*42ms=(45*e6)*(42*e-3)=1890000 bits=230KByte
調節視窗大小即可以理論值為基準,在該值上慢慢增大或減少,即可獲得最好的結果。
Iperf測試TCP頻寬的原理較簡單,即在用戶端和伺服器端建立串連(三向交握)後,用戶端發送一定大小的資料報,並記下發送的時間, 或者用戶端在一定的時間內發送資料,並記下發送的總資料。頻寬的大小等於發送的總資料除以發送的總時間。對伺服器端來說,就是在串連建立時間內,接收的總資料除以所花時間即為伺服器端所測得的頻寬。MSS的大小通過TCP核心介面函數直接獲得。
Iperf測試UDP的效能時,用戶端可以指定UDP資料流的速率。用戶端發送資料時,將根據客戶提供的速率計算資料報發送之間的時延。另外客戶還可以指定發送資料報的大小。每個發送的資料報包含一個ID號,用來惟一地標識該報文。伺服器端則根據該ID號來確定資料報丟失和亂序。當把UDP報文大小設定可以將整個報文放入IP層的包(packet)內時,那麼UDP所測得的報文遺失資料即為IP層包的遺失資料。這提供了一個有效測試包丟失情況的方法。資料報傳輸延遲抖動 (Jitter)的測試由伺服器端完成,客戶發送的報文資料包含有發送時間戳記,伺服器端根據該時間資訊和接收到報文的時間戳記來計算傳輸延遲抖動。傳輸延遲抖動反映傳輸過程中是否平滑。由於它是一個相對值,所以並不需要用戶端和伺服器端時間同步。
4、Iperf實現
Iperf原始碼採用物件導向的C++語言實現,主要包括基本類和實作類別兩部分。基本類提供了實現中需要用到的一些基本的對象,包括隊列、鏈表、時間管理、鎖、條件、線程等,這些代碼不是特定於Iperf應用的,可以移植到其他應用程式。實作類別中主要包括針對Iperf應用的類,包括實現用戶端/伺服器端發送和接收資料的類,以及用於統計資訊的類等。這裡主要討論一下與應用關係最緊密的幾個類,其他的類不做詳述(轉載者註:後面轉載文章有講解)。
Iperf主要類圖結構包括9個類。Iperf 的核心部分均在PerfSocket類中實現,包括用戶端和伺服器端發送和接收資料、頻寬報告、資料丟失及延遲抖動報告,以及視窗大小和MSS報告等功能。其中Speaker和Client為用戶端的對象,Listener、Audience和Server為伺服器端的對象。用戶端和伺服器端的通訊通過三個訊息完成:connect、write以及shutdown。這裡connect不同於TCP中的串連,它還包含一個資料報文,其資訊為雙向測試而傳給伺服器端 的資訊,主要用於雙向測試時讓伺服器端啟動用戶端線程而所需要的資訊。UDP 測試的過程基本上跟TCP類似。UDP報文包含了一個應用報文頭,其主要欄位為報文ID和時間資訊,這個主要是為了測試UDP報文的丟失、亂序以及延遲抖動效能。UDP的第一個報文用來建立串連,不作為應用資料,其資訊為雙向測試而傳給伺服器端的資訊,主要用於雙向測試時讓伺服器端啟動用戶端線程而所需要的資訊。UDP與TCP第一個報文內容的主要區別是UDP報文還包括一個應用報文頭。UDP傳輸結束通過用戶端發送一個FIN的報文來實現,該報文的報文ID為負數,伺服器端接收到FIN報文後即停止接收報文並回送一個 AckFIN報文給客戶,AckFIN報文包含了伺服器端得到的測試資料。
操作舉例:
1)TCP測試
伺服器執行:iperf -s -i 1 -w 1M
用戶端執行:iperf -c host -i 1 -w 1M
其中-w表示TCP window size,host需替換成伺服器位址。
2)UDP測試
伺服器執行:iperf -u -s
用戶端執行:iperf -u -c 10.32.0.254 -b 900M -i 1 -w 1M -t 60
其中-b表示使用頻寬數量,千兆鏈路使用90%容量進行測試就可以了。
5、Iperf提供的庫
在開發Iperf的過程中,開發人員把 Socket編程和多線程編程中經常用到的一些系統調用封裝成對象,屏蔽了底層函數的複雜介面,提供了模組化和物件導向的機制,也為我們提供了一些非常實用的編程工具,我們可以在實現自己的程式時複用這些類。由於這些類實現的原始碼都比較簡單,也為我們修改前人的代碼實現自己的功能提供了方便。
這些類的定義與實現都在原始碼檔案夾的lib子檔案夾下。主要包括以下一些對象:
SocketAddr類:封裝了Socket介面中的網路地址結構(sockaddr_in等)以及各種地址轉換的系統調用(gethostbyname、gethostbyaddr、inet_ntop等);
Socket類:封裝了socket檔案描述符,以及socket、listen、connect等系統調用;
Mutex類以及Condition類:封裝了POSIX標準中的mutex和condition(條件變數)線程同步機制;
Thread類:封裝了POSIX標準中的多線程機制,提供了一種簡單易用的執行緒模式;
Timestamp類:通過Unix系統調用gettimeofday實現了一個時間戳記對象,提供了獲得目前時間戳,計算兩個時間戳記之間的先後關係等方法。
此外,在lib檔案夾中還包括一些Iperf的實現提供的工具 + 生產力函數,包括endian.c檔案中的位元組序轉換函式、gnu_getopt檔案中的命令列參數處理函數、snprintf檔案中的字串格式化函數、signal.c檔案中的與訊號處理有關的函數、 string.c檔案中的字元處理函數、tcp_window_size.c檔案中的TCP視窗大小處理函數等。
6、Iperf工作機制
Iperf是基於Server-Client模式實現的。在測量網路參數時,Iperf區分聽者(Audience)和說者(Speaker)兩種角色。說者向聽者發送一定量的資料,由聽者統計並記錄頻寬、時延抖動等參數。說者的資料全部發送完成後,聽者通過向說者回送一個資料包,將測量資料告知說者。這樣,在說者和聽者兩邊都可以顯示記錄的資料。如果網路過於擁塞或者誤碼率較高,當聽者會送的資料包無法被說者接收到時,說者無法顯示完整的測量資料,而只報告本地記錄的部分網路參數,發送的資料量、發送時間、發送頻寬等,像時延抖動等參數在說者一側則無法獲得(因此,在報告時,伺服器和用戶端所得到的資訊是不同的)。 Iperf提供了三種測量模式:Normal、Tradeoff、Dualtest。對於每一種模式,使用者都可以通過-P選項指定同時測量的並行線程數。以下的討論假設使用者的並行線程數為P個。 在Normal模式下,Client產生P個說者線程,並行向Server發送資料。Server每接收到一個說者的資料,就產生一個聽者線程,負責與說者間的通訊。Client有P個並行的說者線程,而Server有P個並行的聽者線程,兩者之間共有P個串連同時收發資料。測試結束後,Server端的每個聽者向自己對應的說者回送測得的網路參數。 在Tradeoff模式下,首先進行Normal模式下的測試過程,然後Server和Client互換角色。Server產生P個說者線程,同時向Client發送資料。Client對應每個說者產生對應的一個聽者線程用於接收資料並測量參數。最後,有Client端的聽者向Server端的說者回饋測量結果。這樣就可以測量兩個方向上的網路參數了。 對於Dualtest模式同樣可以測試兩個方向上的網路參數,與Tradeoff模式的不同在於,在Dualtest模式下,由Server到Client方向上的網路測試與由Client到Server方向上的網路測試是同時進行的。Client產生P個說者和P個聽者線程,說者向Server端發送資料,聽者等待接收Server端的說者發送的資料。Server端也進行同樣的操作。在Server端和Client端之間同時存在2P個網路連接,其中有P個串連的資料由Client流向Server,另外P個串連的資料由Server流向Client。因此,Dualtest的模式需要的測試時間是Tradeoff模式的一半。 在三種模式下,除了P個聽者或說者進程,在Server和Client兩側均存在一個監控線程(monitor thread)。監控線程的作用包括: *產生說者或聽者線程; *同步所有說者或聽者的動作(開始發送、結束髮送等); *計算並報告所有說者或聽者的累計測量資料。 在監控線程的控制下,所有P個線程間就可以實現同步和資訊共用。說者線程或聽者線程向一個公用的資料區寫入測試結果資料(此資料區位於實現監控線程的對象中),由監控線程讀取並處理。通過互斥鎖(Mutex)實現對該資料區的同步訪問。Server可以同時接收來自不同Client的串連,這些串連是通過Client的IP地址標識的。Server將所有Client的串連資訊組織成一個單向鏈表,每個Client對應鏈表中的一項,該項包括該Client的地址結構(sockaddr)以及實現與該Client對應的監控線程的對象(我們稱之為監控對象),所有與此Client相關的聽者對象和說者對象都是由該監控線程產生的。 Iperf中的主要類:
PerfSocket類: PerfSocket類以Socket為基類派生而來。該類實現了Iperf用於通訊的大多數功能,包括髮送UDP資料包(Send_UDP)、接收UDP資料包(Recv_UDP)、發送TCP資料包(Send_TCP)、接收TCP資料包(Recv_TCP)以及傳輸初始化、報告網路參數、發送/回複結束包等。 Notify類: Notify類是Iperf中的另一個主要基類。它實現了對多個並行線程的監控機制。Notify類提供了對所監控線程的開始動作、結束動作進行同步的方法。這些方法主要是通過條件變數(Condition)機制來實現的。同時,Notify類的執行個體還含有供被監控的線程進行排他(exclusively)訪問(互斥訪問)的資料區。一般是被監控的線程向該資料區中寫入資料。由Notify類的執行個體讀取。 Listener類: Listener類以PerfSocket類和Thread類為基類,屬多重繼承。因為是Thread類的衍生類別,因此 一個Listener執行個體就是一個執行線程,又因為Listener類是PerfSocket類的衍生類別,因此它也具有收發socket資料的能力。 在伺服器端,在伺服器程式啟動後Listener就存在並開始工作。在用戶端,如果使用者指定進行雙向測試(tradeoff或dualtest模式),也 會產生Listener對象。Listener實現的主要功能是在設定的連接埠上監聽串連請求,接收到請求後,若請求來自一個新的客戶,Listener生 成 一個Audience(聽者監控線程,也可稱為聽者監控對象,見下文)執行個體來負責繼續處理與該請求對應的後續操作,如果在請求中指明了要進行 tradeoff或dualtest模式的測量,Listener就產生一個Speaker(說者監控線程,也可稱為說者監控對象,見下文)執行個體來負責發 起到客戶的反向串連;如果請求來自一個已經存在的客戶,Listener通過該客戶對應的Audience執行個體的方法使該Audience執行個體產生一個聽 者線程進行處理該串連(這發生在多線程並行測量的情況下)。完成這些工作後,Listener線程返回繼續監聽。 Audience類: Audience類以Thread類和Notify為基類,屬多重繼承。一個Audience執行個體對應一個執行線程且具有監控其他線程的功能。Audience執行個體(線程)的主要功能是作為聽者線程的監控線程。 它首先產生一個聽者線程(聽者線程通過Server類實現,見下文),之後負責維護並報告所用聽者線程測量結果的累計值,在對聽者線程的結束事件同步之 後,Audience線程退出。Listener線程在接收到一 個已有客戶的串連請求時,也會通過Audience執行個體產生新的Server執行個體。在伺服器端,一個客戶對應一個Audience執行個體,所有的 Audience執行個體組織成一個鏈表。 Speaker類: Speaker類同Audience類一樣,也以Thread類和Notify類為基類。它實現了說者線程的監控線程。 它首先產生若干說者線程(聽者線程通過Client類實現,見下文),對所有說者線程的開始事件進行同步,之後負責維護並報告所用說者線程測量結果的累計 值,在對說者線程的結束事件同步之後,Speaker線程退出。此外,在Speaker線程看是運行時,還會根據是否進行雙向測試產生Listener生 成執行個體,具體情況會在下文中介紹。在用戶端程式開始運行後,Speaker線程就開始工作了。當伺服器端收到雙向測試的請求時,也會產生Speaker實 例(線程)。 Server類: Server類以PerfSocket類和Thread類為基類,實現了聽者進程。它接收對端的說者對象發來的資料,記錄資料量、延遲抖動等網路參數,列印測試結果,修改聽者監控進程(Audience執行個體)的累計資料區,並在收到說者的最後一個資料包時將測試結果回送給說者進程。 Client類: Server類以PerfSocket類和Thread類為基類,實現了聽者進程。它接收對端的說者對象發來的資料,記錄資料量、延遲抖動等網路參數,列印測試結果,修改聽者監控進程(Audience執行個體)的累計資料區,並在收到說者的最後一個資料包時將測試結果回送給說者進程。 綜上,Client類與Server類對應,分別實現了說者線程和聽者線程;Speaker類和Audience類對應,分別實現了說者監控線程和聽者監控線程。Listener類是監聽線程;所有的Client執行個體由Speaker執行個體產生,所有的Server執行個體是由Listener執行個體觸發Audience執行個體產生。