我是C的初学者,我遇到了一个有趣的问题。
我正在捕获端口80上的所有传出数据包,我想计算每个IP的传输速度。但问题是我不知道如何对这些IP地址进行分组,在PHP中我可以通过IP创建数组和索引条目并搜索数组,如果IP索引已经存在,则传输更新值字节,然后将其除以经过的秒数,我有B / s的传输速度。但在C中,我不能这样做。
建议我如何实现我的问题,因为现在我只能计算整体传输速度。
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
答案 0 :(得分:2)
在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;
}
出于性能原因,它的结构为堆栈(最后添加的元素首先出现)。
答案 1 :(得分:0)
在 C ++ 中,如果您需要一个可以通过包含IP的字符串访问的关联容器,则可以使用map< string, float >
类型的map container(当然,如果你使用字符串存储IP)
然后,您只需执行yourMapName[IPaddress]
。
如果您需要在 C 中执行此操作,则需要执行包含IP地址的struct
(如果它是纯C,您可能会使用char*
,然后你需要做一个这样的结构数组和一个函数,它在数组中搜索给定unsigned int
的结构并添加到int中,或者添加一个新的条目数组。
如果您需要使结构数组灵活(因为您不知道要连接多少个IP),您需要学习如何使用char*
和malloc
C函数
因此,如果你没有坚持使用纯C - 那么在C ++中这样做会更直接。只是一个提示,这是你的选择。
答案 2 :(得分:0)
不要自己实现,使用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