2016-11-22 13 views
1

私はHTTPのスレッドプロキシを使用しています。つまり、クライアントからのリクエストごとにスレッドを生成します:今はビット/秒(bps)やパケット/秒(pps)libpcapを使用して接続に関する統計を収集する

スレッドは接続を処理する場合、すべてのパケットに対してbpsとppsを計算しません。これを別のスレッドに残します。

クライアントからのHTTP要求ごとにスレッドを作成し、プロキシが要求されたリモートサーバに正常に接続した場合、proxtは実際のHTTP要求をサーバに送信し、データをルーティングする前に接続スレッドはログスレッドを作成します:接続がオープンになるまでbpsとppsを計算します。接続スレッドは、どのパケットをフィルタリングするか(ローカルIPアドレス、ローカルポート、リモートIPアドレス、リモートポート)についてログスレッドに通知します。したがって、すべてのログスレッドは親接続スレッドからのパケットのみをフィルタリングします。

パケットごとにbpsとppsを計算する際に問題が発生しています。ここで

は、ロギング、スレッド内のパケットの私のループ・キャプチャーの擬似コードです:

// pcap variables 
pcap_t *handle; 
struct pcap_pkthdr *header; 
const u_char *pkt_data; 
// timevals used to calculate delay from last filtered packet 
struct timeval oldTimevalUpload; 
struct timeval oldTimevalDownload;  
memset(&oldTimevalUpload, 0, sizeof(oldTimevalUpload)); 
memset(&oldTimevalDownload, 0, sizeof(oldTimevalDownload)); 

// stopLogging is a boolean flag declared in connection "parent" thread: 
// it is set to false when connection thread has done sending and 
// receiving data and connection is going to be closed 
while (((res = pcap_next_ex(handle, &header, &pkt_data)) >= 0) && (!stopLogging)) { 
    // check res 
    if (packet is upload) { 
     struct timeval difference; 
     timeval_subtract(&difference, &(header->ts), &oldTimevalUpload); 
     long long delay = (difference.tv_sec * 1000000) + difference.tv_usec; 
     long long acceptedPackets = ((long long)(pkt_data)) * 1000000; 
     long long acceptedBits = ((long long)(pkt_data+8)) * 8 * 1000000; 
     long long pps = acceptedPackets/delay; 
     long long bps = acceptedBits/delay; 
     debugRed(host << ", UPLOAD DIVIDE ACCEPTED PKTS " << acceptedPackets << 
      " AND ACCEPTED BITS " << acceptedBits << " PER DELAY " << delay << 
      " IS PPS " << pps << " AND BPS " << bps); 
     oldTimevalUpload.tv_sec = header->ts.tv_sec; 
     oldTimevalUpload.tv_usec = header->ts.tv_usec; 
    } else if (packet is download) { 
     // basically the same as above 
    } 
} 
debug("Quit logging connection " << localIPaddr << ":" << localPort << " and " 
    << remoteIPaddr << ":" << remotePort); 
pcap_close(handle); 

そしてここでは、サンプル出力です:

www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 1479811349890053 IS PPS 0 AND BPS 0 
www.netflix.com DOWNLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 1479811350032141 IS PPS 0 AND BPS 0 
www.netflix.com DOWNLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 4344 IS PPS 22845174953 AND BPS 182761414364 
www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 146464 IS PPS 677568822 AND BPS 5420551015 
www.netflix.com DOWNLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 2815 IS PPS 35253797513 AND BPS 282030402841 
www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 2808 IS PPS 35341680911 AND BPS 282733470085 
www.netflix.com DOWNLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 1120 IS PPS 88606642857 AND BPS 708853200000 
www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 1134 IS PPS 87512733686 AND BPS 700101925925 
www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 39658 IS PPS 2502381360 AND BPS 20019052498 
www.netflix.com DOWNLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 176317 IS PPS 562846690 AND BPS 4502773890 
www.netflix.com UPLOAD, DIVIDE ACCEPTED PKTS 99239440000000 AND ACCEPTED BITS 793915584000000 PER DELAY 136687 IS PPS 726034224 AND BPS 5808274261 

私は、私のホームネットワークが500 MBps以上に耐えられる知っていたことはありません何かが間違っているはずです。

This pageは、bpsとppsを計算する方法を示しており、acceptedBitsに8 charsのシフトを説明していますが、とにかくそれを報告します。ここでは、機能pcap_next_exの第二と第三のパラメータを見ることができます:

Starting from the beginning of <code>pkt_data</code>, you can see the first <code>long integer</code> bytes represent accepted bytes

基本的に、私は彼が言ったことをすべてやりました!なぜ私は大きくて奇妙なbpsとppsになるのですか?

Ubuntuで作業する14.04; libpcapバージョンを確認する方法を知っているが、locate libpcapはこれを与えないでください:あなたのコードで

/home/dexter/Desktop/wireshark-1.99.9/wiretap/libpcap.c 
/home/dexter/Desktop/wireshark-1.99.9/wiretap/libpcap.h 
/usr/lib/x86_64-linux-gnu/libpcap.a 
/usr/lib/x86_64-linux-gnu/libpcap.so 
/usr/lib/x86_64-linux-gnu/libpcap.so.0.8 
/usr/lib/x86_64-linux-gnu/libpcap.so.1.5.3 
/usr/share/doc/libpcap-dev 
/usr/share/doc/libpcap0.8 
/usr/share/doc/libpcap0.8-dev 
/usr/share/doc/libpcap-dev/changelog.Debian.gz 
/usr/share/doc/libpcap-dev/copyright 
/usr/share/doc/libpcap0.8/CREDITS.gz 
/usr/share/doc/libpcap0.8/README.Debian 
/usr/share/doc/libpcap0.8/README.gz 
/usr/share/doc/libpcap0.8/changelog.Debian.gz 
/usr/share/doc/libpcap0.8/copyright 
/usr/share/doc/libpcap0.8-dev/changelog.Debian.gz 
/usr/share/doc/libpcap0.8-dev/copyright 
/var/lib/dpkg/info/libpcap-dev.[list,md5sums] 
/var/lib/dpkg/info/libpcap0.8-dev.[list,md5sums,preinst] 
/var/lib/dpkg/info/libpcap0.8:amd64.[list,md5sums,postinst,postrm,shlibs,symbols] 

答えて

1

long long acceptedPackets = ((long long)(pkt_data)) * 1000000; 
long long acceptedBits = ((long long)(pkt_data+8)) * 8 * 1000000; 

をpkt_dataはポインタですが。

パケットデータのアドレスを基本的に取得して、long longに変換し、8行目(2行目)に追加し、定数を乗算して、その値が意味的に間違っているとみなします。データ型を考慮して、ポインタを逆参照する必要があります(pkt_datalong longへのポインタに変換してください)。コードで

:たとえば

long long acceptedPackets = (*(long long*)(pkt_data)) * 1000000; 
long long acceptedBits = (*(long long*)(pkt_data+8)) * 8 * 1000000; 
// this also works: 
//long long acceptedPackets = *(long long*)pkt_data * 1000000; 
//long long acceptedBits = *((long long*)pkt_data + 1) * 8 * 1000000; 

、参照http://ideone.com/JqmRre

EDIT

this guideから:

は、最後の引数は、それらの最も興味深いですすべて、そして最も多くの平均的な初心者のpcapプログラマーに混乱します。これはu_char型への別のポインタ であり、そしてそれはpkt_dataがパケットの内容そのものであることを意味する全体パケット

を含む データのチャンクの最初のバイトを指します。パケットの最初の16バイトに希望の情報が含まれていない限り(これには未処理のパケットが含まれているため、ETH、IP、TCP/UDPヘッダーがあるため)、そのデータは使用できません。 PPSメトリックを取得するには、ループ内に単純なカウンタを実装する必要があります(フレームごとにメトリックが印刷されるため、単純なlong long pps = (long long)(1.0/delay);で十分です)。浮動小数点数はであることに注意してください。 。。あなたがC++ 11を使用しているので、あなたは、フレームのヘッダ情報を使用する必要がありますのでlong long bps = (long long)(header->caplen * 8.0/delay);が何をすべき

注意点として、時間メトリックに対して、chronoを使用してみてくださいそれは体timevalより明確かつ安全です:。

#include <chrono>を追加してください。

最終コードは次のようになります。

// pcap variables 
pcap_t *handle; 
struct pcap_pkthdr *header; 
const u_char *pkt_data; 
// Use of high_resolution_clock 
std::chrono::high_resolution_clock::time_point oldTimeUpload = std::chrono::high_resolution_clock::now(); 
std::chrono::high_resolution_clock::time_point oldTimeDownload = std::chrono::high_resolution_clock::now(); 

// stopLogging is a boolean flag declared in connection "parent" thread: 
// it is set to false when connection thread has done sending and 
// receiving data and connection is going to be closed 
while (((res = pcap_next_ex(handle, &header, &pkt_data)) >= 0) && (!stopLogging)) { 
    // check res 
    if (packet is upload) { 
     std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now(); 
     long long delay = std::chrono::duration_cast<std::chrono::nanoseconds>(now - oldTimeUpload).count(); 
     long long pps = (long long)(1000000000.0/delay); 
     long long bps = (long long)(header->caplen * 8 * 1000000000.0/delay); 
     debugRed(host << ", UPLOAD DIVIDE PER DELAY " << delay << 
      " IS PPS " << pps << " AND BPS " << bps); 
     oldTimevalUpload.tv_sec = header->ts.tv_sec; 
     oldTimevalUpload.tv_usec = header->ts.tv_usec; 
    } else if (packet is download) { 
     // basically the same as above 
    } 
} 
debug("Quit logging connection " << localIPaddr << ":" << localPort << " and " 
    << remoteIPaddr << ":" << remotePort); 
pcap_close(handle); 
+0

私はあなたのアドバイスに従っ:今私は、負の数のXD 'www.youtube.comダウンロードDIVIDE ACCEPTED PKTS -9153173178195537408、受け入れBITS -2444556543073261568 DELAY PERを持っています1479847752267586はDELAY 2745 PER -2444556543073261568 PPS -6185と-1651 BPS www.youtube.comダウンロードDIVIDE ACCEPTED PKTS -9153173178195537408、受け入れBITS PPS -3334489318104020とBPS -890548831720678 www.youtube.com UPLOADのDIVIDE ACCEPTED PKTS IS IS -1866508824056485888と受け入れられたビット-2458024441489261568 PER DELAY 1479847752270362 IS PPS -1261 AND BPS -1660'およびs o on ... – elmazzun

+0

私の編集を確認してください –

0

別のスレッドではなく、別のプロセスでppsとbpsの計算を行うのはどうですか? HttpAnalyzerユーティリティは、ネットワークインターフェイスからHTTPパケットを直接キャプチャし、pps、bpsなどの統計情報を計算することをお勧めします。

オープンソースなので、あなたの目的に合うようにコードを変更するか、そのまま使用することができます。ここで

は、このユーティリティの出力例です:

STATS SUMMARY 
============= 

General stats 
-------------------- 

Sample time:          18.374 [Seconds] 
Number of HTTP packets:       5662 [Packets] 
Rate of HTTP packets:       291.910 [Packets/sec] 
Number of HTTP flows:        55 [Flows] 
Rate of HTTP flows:        2.836 [Flows/sec] 
Number of HTTP pipelining flows:      0 [Flows] 
Number of HTTP transactions:      322 [Transactions] 
Rate of HTTP transactions:      16.601 [Transactions/sec] 
Total HTTP data:        5916120 [Bytes] 
Rate of HTTP data:       305011.600 [Bytes/sec] 
Average packets per flow:      102.945 [Packets] 
Average transactions per flow:     5.963 [Transactions] 
Average data per flow:      107565.818 [Bytes] 

HTTP request stats 
-------------------- 

Number of HTTP requests:       323 [Requests] 
Rate of HTTP requests:       16.653 [Requests/sec] 
Total data in headers:       188596 [Bytes] 
Average header size:       583.889 [Bytes] 

HTTP response stats 
-------------------- 

Number of HTTP responses:       332 [Responses] 
Rate of HTTP responses:       17.117 [Responses/sec] 
Total data in headers:       119577 [Bytes] 
Average header size:       360.172 [Bytes] 
Num of responses with content-length:    320 [Responses] 
Total body size (may be compressed):   5409410 [Bytes] 
Average body size:       16904.406 [Bytes] 

HTTP request methods 
-------------------- 

| Method | Count | 
--------------------- 
| GET  | 321 | 
| POST  | 2  | 
--------------------- 

Hostnames count 
-------------------- 

| Hostname         | Count | 
---------------------------------------------------- 
| images1.teny.co.qq      | 180 | 
| www.teny.co.qq       | 82 | 
| go.teny.co.qq       | 14 | 
| www.niwwin.co.qq       | 8  | 
| az835984.vo.msecnd.net     | 5  | 
| asset.pagefair.com      | 3  | 
| b.scorecardresearch.com     | 3  | 
| cdn.oolala.com       | 3  | 
| asset.pagefair.net      | 2  | 
| dy2.teny.co.qq       | 2  | 
| ecdn.firstimpression.io     | 2  | 
| pagead2.googlesyndication.com   | 2  | 
| server.exposebox.com      | 2  | 
| totalmedia2.teny.co.qq     | 2  | 
| vrp.mybrain.com       | 1  | 
| trc.oolala.com       | 1  | 
| zdwidget3-bs.sphereup.com    | 1  | 
| vrt.mybrain.com       | 1  | 
| www.googletagmanager.com     | 1  | 
| a.visualrevenue.com      | 1  | 
| tpc.googlesyndication.com    | 1  | 
| static.dynamicyield.com     | 1  | 
| st.dynamicyield.com      | 1  | 
| sf.exposebox.com       | 1  | 
| mediadownload.teny.co.qq     | 1  | 
| cdn.firstimpression.io     | 1  | 
| ajax.googleapis.com      | 1  | 
---------------------------------------------------- 

Status code count 
-------------------- 

| Status Code     | Count | 
---------------------------------------- 
| 200 OK      | 327 | 
| 204 No Content    | 1  | 
| 301 Moved Permanently  | 1  | 
| 302 Moved Temporarily  | 1  | 
| 304 Not Modified    | 2  | 
---------------------------------------- 

Content-type count 
-------------------- 

| Content-type     | Count | 
------------------------------------------ 
| application/javascript   | 11 | 
| application/json    | 1  | 
| application/x-javascript  | 23 | 
| image/gif      | 22 | 
| image/jpeg      | 157 | 
| image/png      | 85 | 
| text/css      | 9  | 
| text/html      | 8  | 
| text/javascript    | 13 | 
------------------------------------------ 
関連する問題