匹配(搜索)C列表中的URL(实施白名单或黑名单)的最佳方法?

时间:2013-02-12 09:00:54

标签: c string list hash match

我正在编写代理服务器。它对列表中匹配的网站应用不同的规则。例如,我们可以阻止列表A并使用另一个代理来获取列表B的内容。

例如,列表A:

.google.com
blogger.com
sourceforge.net
ytimg.com
http://media-cache-*.pinterest.com/*
images-amazon.com
*.amazonaws.com
twitter.com
fbcdn.net
google-analytics.com
staticflickr.com

列表B:

ytimg.com
youtube.com

目前,匹配功能是:

struct proxy_t *
match_list(char *url) {
  // 2KB line should be enough
  char buf[2048];
  int pos = 0, size;

  struct acllist *al = config->acl_h;
  struct acl *node = al->data; 

  while (node != NULL) { // iterate list
    pos = 0; // position in list file

    size = strlen(node->data); // node->data holds a URL list

    while (1) { // iterate each line in list

      readline(buf, node->data, &pos, size);

      if (buf[0] == 0) break;

      if (strcasestr(url, buf) != NULL 
      || !fnmatch(buf, url, FNM_CASEFOLD)) {

          return node->proxy;
      }
    }
    node = node->next;
  }


  printf("Not Matched\n");

  return config->default_proxy;
}

也就是说,迭代两个列表文件,逐行阅读,使用 strcasestr fnmatch 来匹配单个网址。

工作正常。但是如果列表越来越大,比如每个列表10,000行和5个列表,我认为它不是一个有效的解决方案,因为它是一个O(N)算法。

我正在考虑为每个匹配线添加一个点击计数器。通过对匹配线进行排序,可以减少平均搜索长度。像这样:

.google.com|150
blogger.com|76
sourceforge.net|43
ytimg.com|22

还有其他想法吗?

1 个答案:

答案 0 :(得分:0)

有两种方法可以改善效果。

<强> 1

第一种方法是以某种方式对URL列表进行排序,因此您可以优化其中的搜索。 Quicksort是最快的算法。

Bubble sort更容易实施。

然后您可以使用binary search在列表中进行搜索。 二进制搜索具有对数性能,而您的循环具有线性,因此在大型列表上显着更快。

<强> 2

如果您的网址列表是静态的,您可以使用名为flex的特殊工具,这样您就可以通过阅读它来解析字符串。

这也意味着,当你的某些URL列表被更新时,你必须编写新的代码来解析或创建代码生成器。

这是一种更有效的解析方式,然后是任何类型的排序,因为它只需要N步,当N是你正在解析的URL的长度时,因此你的列表有多长并不重要,只要因为你可以为输入编写正确的扫描仪。