0

我是 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
4

3 回答 3

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;

我进行了一些更改以最适合您的目的,并且没有检查它是否可以编译,如果您无法弄清楚我可以为您提供帮助。

这基本上就是你使用它的方式:你有一个名为 的 IP 列表,my_ip_map默认情况下它是空的。

您可以在其中创建元素或使用以下方法更新它:

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;
}

出于性能原因,其结构为堆栈(最后添加的元素首先出现)。

于 2013-11-08T20:47:34.723 回答
0

C++中,如果您需要一个关联容器,您可以通过包含 IP 的字符串访问它,您可以使用map container类型map< string, float >(当然,如果您使用字符串存储 IP)

然后您可以通过执行来访问元素yourMapName[IPaddress]

如果您需要在C中执行此操作,则需要执行包含 IP 地址的a struct(如果它是纯 C,您可能会使用char*unsigned int具有给定结构的数组char*并添加到 int,或在数组中添加新条目。

如果您需要使结构数组灵活(因为您不知道将连接多少 IP),您需要学习如何使用mallocfreeC 函数。

因此,如果您不拘泥于纯 C,那么在 C++ 中执行此操作会更直接。只是一个提示,这是你的选择。

于 2013-11-08T20:20:54.623 回答
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

https://developer.gnome.org/glib/2.38/glib-Hash-Tables.html

于 2013-11-09T16:37:45.197 回答