[英]How to group transfers by IP address in C to calculate transfer rates?
我是C的初學者,我遇到了一個有趣的問題。
我正在捕獲端口80上的所有傳出數據包,我想計算每個IP的傳輸速度。 但問題是我不知道如何對這些IP地址進行分組,在PHP中我可以通過IP創建數組和索引條目並搜索數組,如果IP索引已經存在,則傳輸更新值字節,然后將其除以經過的秒數,我有B / s的傳輸速度。 但在CI中無法做到這一點。
建議我如何實現我的問題,因為現在我只能計算整體傳輸速度。
t2 = time(0);
time_elapsed = (int) (t2-t1);
if(time_elapsed > 0) {
bytes += Size;
//packets size SUM from all IP addresses, which is incorrect
printf("IP: %s | Size: %d\n\n", inet_ntoa(dest.sin_addr), Size);
}
產量
IP: 77.236.192.100 | Size: 4434
IP: 89.176.81.106 | Size: 43854
IP: 89.176.81.106 | Size: 20494
IP: 89.176.81.106 | Size: 24874
IP: 77.236.192.100 | Size: 7354
IP: 89.176.81.106 | Size: 39474
IP: 89.176.81.106 | Size: 16114
在C中,您可以使用帶有指針的鏈式節點,也稱為隊列,列表或堆棧(取決於其結構如何)。 我有一個可能適合您的代碼:
struct _ip_map_node {
struct _ip_map_node* next;
unsigned long ip;
unsigned long transfered;
unsigned long time;
};
typedef struct _ip_map_node ip_map_node;
ip_map_node* update_or_create_ip_map_node(ip_map_node** queue, unsigned long ip, unsigned long transfered) {
ip_map_node* node = *queue;
while (node) {
if (node->ip == ip) {
node->transfered += transfered;
return node;
}
node = node->next;
}
node = malloc(sizeof(ip_map_node));
node->next = *queue;
*queue = node;
node->ip = ip;
node->transfered = transfered;
node->time = time(NULL);
return node;
}
void remove_ip_map_node(ip_map_node** queue, unsigned long ip) {
ip_map_node* last = NULL;
ip_map_node* curr = *queue;
while (curr) {
if (curr->ip == ip) {
if (last)
last->next = curr->next;
else
*queue = curr->next;
free(curr);
break;
}
last = curr;
curr = curr->next;
}
}
ip_map_node* my_ip_map = NULL;
我做了一些更改以最適合您的目的,並沒有檢查它是否編譯,如果您無法搞清楚我可以幫助您。
這基本上就是你如何使用它:你有一個名為my_ip_map
的IP列表,默認為空。
您可以在其中創建元素或使用以下命令更新它:
ip_map_node* node = update_or_create_ip_map_node(&my_ip_map, dest.sin_addr.s_addr, data_size);
其中data_size
是此時轉移到該IP的字節數。 它將自動匯總為先前發送到同一IP的金額。
然后該node
具有以下屬性:
node->ip; // The IP in numeric format, use inet_ntoa() to transform it
node->transfered; // The amount that was transfered to that IP so far
node->time; // the time(NULL) when the first packet was sent to this IP
您現在可以使用node->transfered / (time(NULL) - node->time)
獲取傳輸速度 - 請注意,因為除零會崩潰。
如果要每隔幾秒重置一次此節點,您可以使用:
node->transfered = 0;
node->time = time(NULL);
或者刪除它:
remove_ip_map_node(&my_ip_map, dest.sin_addr);
並且可以在列表中運行所有IP,例如:
ip_map_node* node = my_ip_map;
while(node) {
printf("%s, %d\n", inet_ntoa(*(struct in_addr *)&node->ip), node->transfered);
node = node->next;
}
出於性能原因,它的結構為堆棧(最后添加的元素首先出現)。
在C ++中 ,如果需要一個關聯容器(可以通過包含IP的字符串訪問),可以使用map< string, float >
類型的映射容器 (當然,如果使用字符串存儲IP)
然后你可以通過執行你的yourMapName[IPaddress]
來訪問元素。
如果你需要在C中做,你需要做一個包含IP地址的struct
(如果它是純C,你可能會使用char*
和unsigned int
。那么你需要做一個這樣的結構數組和一個函數,它在數組中搜索具有給定char*
的結構並添加到int中,或者在數組中添加一個新條目。
如果您需要使結構數組靈活(因為您不知道將連接多少IP),您將需要學習如何使用malloc
和free
C函數。
所以,如果你沒有堅持使用純C - 那么在C ++中這樣做會更直接。 只是一個提示,這是你的選擇。
不要自己實現,使用C中可用的大量庫之一。使用glib的示例:
#include <glib.h>
#include <stdio.h>
unsigned lookup(GHashTable *dict, const char *key)
{
return GPOINTER_TO_UINT(g_hash_table_lookup(dict, key));
}
void accumulate(GHashTable *dict, char *key, unsigned increment)
{
unsigned value;
value = lookup(dict, key);
g_hash_table_insert(dict, key, GUINT_TO_POINTER(value + increment));
}
int main(void)
{
GHashTable *ip;
ip = g_hash_table_new(g_str_hash, g_str_equal);
accumulate(ip, "10.1.1.1", 0);
accumulate(ip, "10.10.10.10", 2);
accumulate(ip, "10.1.1.1", 2);
accumulate(ip, "10.1.1.1", 3);
accumulate(ip, "10.2.2.2", 10);
printf("%u\n", lookup(ip, "10.1.1.1"));
printf("%u\n", lookup(ip, "10.10.10.10"));
printf("%u\n", lookup(ip, "10.2.2.2"));
g_hash_table_unref(ip);
return 0;
}
輸出:
$ ./hash
5
2
10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.