閱讀804 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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

進行上下行帶寬測試。


3、Iperf工作原理

    Iperf主要的TCP功能是測試基於特定路徑的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應用的類,包括實現客戶端/服務器發送和接收數據的類,以及用於用於管理client和server的類等。這裏主要討論一下與應用關係最緊密的幾個類,其他的類不做詳述。

    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區分Client對象Server對象兩種角色。Client對象Server對象發送一定量的數據,由Server對象統計並記錄帶寬、時延抖動等參數。Client對象的數據全部發送完成後,Server對象通過向Client對象回送一個數據包,將測量數據反饋給Client對象。這樣,在ClientServer兩邊都可以顯示記錄的數據。如果網絡過於擁塞或者誤碼率較高,當Server回送的數據包無法被Client接收到時,Client無法顯示完整的測量數據,而隻報告本地記錄的部分網絡測試結果,發送的數據量、發送時間、發送帶寬等,像時延抖動等參數在Client一側則無法獲得(因此,在報告時,服務器和客戶端所得到的信息可能是不同的)。

    Iperf提供了三種測模式:Normal、Tradeoff、Dualtest。對於每一種模式,用戶都可以通過-P選項指定同時測量的並行線程數。以下的討論中,設用戶的並行線程數為P個。

    在Normal模式下,客戶端首先生成Speaker對象,Speaker對象根據參數設置生成P個Client對象然後並行服務器發送數據。服務器通過Listener對象在套接字監聽網絡連接,當Listener接收到一個Client發送的數據時,首先判斷是否有Audience處理該主機(僅指IP地址),如果有,便將Audience與此Client關聯,如果沒有,便生成一Audience對象,負責與Speaker對象間的通信。客戶端有P個並行的Client對象(由Speaker管理),而服務器有P個並行的Server對象(由Audience管理),兩者之間共有P個連接同時收發數據。測試結束後,服務器端的每個Server對象調用基類Report*()係列函數向自己對應的Client對象反饋測得的網絡參數。

    在Tradeoff模式下,首先進行Normal模式下的測試過程,然後客戶端服務器互換角色。原服務器生成P個Client對象,同時向原客戶端發送數據。原客戶端對應每個Client對象生成應的Server對象,用於接收數據並測量參數。最後,由原客戶端Server對象原服務器端的Client對象反饋測量結果。這樣就可以測量兩個方向上的網絡參數了。

    對於Dualtest模式,該模式同樣用於測試兩個方向上的網絡參數,與Tradeoff模式的不同在於,在Dualtest模式下,由服務器客戶端方向上的網絡測試與由客戶端服務器方向上的網絡測試是同時進行的。客戶端生成P個Client對象和P個Server對象Client對象服務器端發送數據,Server對象等待接收服務器端的Client對象發送的數據。服務器端也進行同樣的操作。在客戶端和服務器端之間同時存在 2P個網絡連接,其中有P個連接的數據由客戶端流向服務器,另外P個連接的數據由服務器流向客戶端。因此,Dualtest的模式需要的測試時間是Tradeoff模式的一半。

    在三種模式下,除了P個Client對象Server對象,在服務器端客戶端兩側均存在一個監控進程實例(monitor thread),分別對應於Audience和Speaker監控進程實例的作用包括:

    *生成說者或聽者線程;

    *同步所有說者或聽者的動作(開始發送、結束發送等);

    *計算並報告所有說者或聽者的累計測量數據。

    在監控線程的控製下,所有P個Client或Server對象間就可以實現同步和信息共享。Client對象Server、對象向一個公共的數據區寫入測試結果數據(此數據區位於實現監控線程的對象中),由監控線程讀取並處理。通過互斥鎖(Mutex)實現對該數據區的同步訪問。服務器端通過Listener類可以同時接收來自不同客戶端的連接,這些連接是通過客戶端的IP地址標識的。服務器將所有客戶端的連接信息組織成一個單向鏈表,每個客戶端連接對應鏈表中的一項,該項包括該客戶端的地址結構(sockaddr)以及實現與該client對應server類的監控線程Audience的對象

    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(Server監控線程,也可稱為Server監控對象)對象來負責繼續處理與該請求對應的後續操作,如果在請求中指明了要進行 tradeoff或dualtest模式的測量,Listener就生成一個Speaker(Client監控線程,也可稱為Client監控對象)實例來負責發起到客戶的反向連接;如果請求來自一個已經存在的客戶,Listener通過該客戶對應的Audience實例的方法使該Audience實例生成一個Server對象進行處理該連接(這發生在多線程並行測量的情況下)。完成這些工作後,Listener線程返回繼續監聽。

    Audience類:

    Audience類以Thread類和Notify為基類,屬多重繼承。一個Audience實例對應一個執行線程且具有監控其他線程的功能。Audience實例的主要功能是作為Server對象的監控線程。 它首先生成一個Server對象,之後負責維護並報告所用聽者線程測量結果的累計值,在對聽者線程的結束事件同步之後,Audience線程退出。Listener線程在接收到一個已有客戶的連接請求時,也會通過Audience實例生成新的Server對象實例。在服務器端,一個客戶對應一個Audience實例,所有的 Audience實例組織成一個鏈表。

    Speaker類:

    Speaker類同Audience類一樣,也以Thread類和Notify類為基類。它實現了Client對象的監控線程。 它首先生成若幹Client對象,對所有Client對象的開始事件進行同步,之後負責維護並報告所用Client對象測量結果的累計值,在對Client對象的結束事件同步之後,Speaker退出。此外,Speaker運行時,還會根據是否進行雙向測試來由Listener生成實例。在客戶端程序開始運行後,Speaker線程就開始工作了。當服務器端收到雙向測試的請求時,也會生成Speaker實例(線程)。

    Server類:

   Server類以PerfSocket類和Thread類為基類,實現了服務器端進程。它接收對端的Client對象發來的數據,記錄數據量、延遲抖動等網絡參數,打印測試結果, 修改Audience實例的累計數據區,並在收到Client對象的最後一個數據包時將測試結果回送給Client

    Client類:

    Client類以PerfSocket類和Thread類為基類,實現了客戶端進程。它建立於遠端服務器的連接,執行發送TCP/UDP數據包的過程,判斷發送結束標誌,接收服務器端Server對象反饋信息,同時打印出相應的網絡測試結果。

    綜上,Client類與Server類對應,分別實現了客戶端進程服務器進程;Speaker類和Audience類對應,分別實現了Client對象監控實例Server對象監控實例。Listener類是監聽對象;所有的Client實例由Speaker實例生成,所有的Server實例是由Listener實例觸發Audience實例生成。

最後更新:2017-04-03 05:39:41

  上一篇:go 論創業者心態心智
  下一篇:go poj 2090 Two-Stacks Solitaire