2014-09-01 58 views
0

如果一個執行例如iperf -c 178.62.60.141 -fm -b 100m -u -t 30 -i 10,然後每間隔10秒後,客戶端的Iperf打印出它在mebibytes已經傳送的數據量:Iperf 2.x客戶端如何檢測它發送的流量?

[email protected]:~# iperf -c 178.62.60.141 -fm -b 100m -u -t 30 -i 10 
WARNING: option -b implies udp testing 
------------------------------------------------------------ 
Client connecting to 178.62.60.141, UDP port 5001 
Sending 1470 byte datagrams 
UDP buffer size: 0.22 MByte (default) 
------------------------------------------------------------ 
[ 3] local 146.185.187.148 port 37660 connected with 178.62.60.141 port 5001 
[ ID] Interval  Transfer  Bandwidth 
[ 3] 0.0-10.0 sec 119 MBytes 100 Mbits/sec 
[ 3] 10.0-20.0 sec 119 MBytes 100 Mbits/sec 
[ 3] 20.0-30.0 sec 119 MBytes 100 Mbits/sec 
[ 3] 0.0-30.0 sec 358 MBytes 100 Mbits/sec 
[ 3] Sent 255661 datagrams 

同樣如此TCP。實際上,傳輸的數據和帶寬在之後打印出,並且傳輸的數據有時會比「-b」標誌指定的帶寬多一些或少一些,這應該意味着Iperf客戶端實際上以某種方式對發送的數據進行計數並不僅僅打印「-b」(帶寬)標誌的參數。但是,Iperf客戶端如何計算它發送的數據量?它肯定不會在低級別上執行此操作,因爲如果我在tc中引入了10%的數據包丟失,請執行iperf -c 178.62.60.141 -fm -b 100m -u -t 30 -i 10,然後比較Iperf客戶端認爲它發送的數據包(來自Iperf客戶端輸出)與實際連接到數據包的數據量從ip -s link show dev eth0輸出),然後Iperf客戶端認爲它發送了大於250k的數據報,而實際上它只是超過了230k。如果我用tc令牌桶過濾器排隊紀律來監視流量,也就是說,根據Iperf客戶端,它已經以100Mbps發送流量,而實際流量由警察監管,所以這同樣適用。

如果我嘗試分析Iperf的源代碼(http://ftp.de.debian.org/debian/pool/main/i/iperf/iperf_2.0.5.orig.tar.gz),那麼據我瞭解,客戶端連接使用常規connect()系統調用在src目錄下的Client.cpp文件中編碼?我想報告是在Reporter.c文件中編寫的,但是對於我來說這太複雜了。有人可以解釋(代碼示例)Iperf 2.x客戶端如何檢測它發送的流量?

回答

3

在查看源代碼之前,這看起來相當簡單。客戶應該知道它發送了多少東西。畢竟,它發送了它。因此,它必須查看系統時鐘,獲取發送給定數量的數據所需的時間,並計算出速率。

而且,現在已經看到了Reporter.c--正如預期的那樣,存在各種各樣的gettimeofday()系統調用,它們捕獲系​​統時鐘的值。

此實用程序發送的流量不能是如此大的謎團。畢竟,它發送了它,所以它應該知道有多少。

+0

我也注意到'Reporter.c'和'Client.cpp'文件中的'gettimeofday()'函數,但我不明白在什麼時間發生。也許這只是我,但代碼本身也看起來有點模糊。我也希望發送UDP數據報是使用'write()'函數完成的,並且在發送數據到套接字之前和之後調用'gettimeofday()'完成帶寬測量,但是我希望從中獲得相應的代碼片段Iperf源代碼。 – Martin 2014-09-04 10:45:45

1

您可以追蹤寫入總金額的send(), write() or *printf()的返回值......然後每X時間打印一次(當前 - 最後一次),然後最後設置爲當前值。

在iperf的,這是通過調用做int iperf_tcp_send()(對於UDP類似功能)

的返回值write(), send() and the *printf()功能是寫入的字符數。如果你在不使用返回值的情況下使用這些函數,那麼以(void)作爲前綴是明智的,但是我看到很多代碼忽略了它,導致許多程序員認爲它們是無效函數。

此外,寫入調用並不保證發送所有數據,所以返回值對於確保完整寫入整個緩衝區是非常有用的。看這個檢查的一個很好的例子Rob Landley's Toybox implementation of writeall()