2015-08-28 36 views
1

我正在使用基于Elixir的网络扫描程序。 我的目标是能够在代理(简单)中存储IP地址列表,并在该代理上循环工作人员,以便他们获取列表头并启动扫描/探测功能(并不那么容易)。虽然这可能听起来像某种理论的东西,但我可以提供代码片段,如果它有帮助。循环工人通过基于代理的IP地址列表

编辑︰显然我设法弄清楚如何做到这一点(我想这是怎么会这样做)。

defmodule Find3r.Worker do 
use GenServer 
require Logger 

    def start_link, do: GenServer.start_link(__MODULE__, :ok, name: :worker) 

    def init(:ok) do 
    Logger.debug("Worker activated.") 
    {:ok, :ok} 
    end 

    def scan_range(range), do: GenServer.call(__MODULE__, {:scan_range, range}) 

    def handle_call({:scan_range, range}, _from, :ok) do 
    Logger.debug("Scanning #{range}") 
    {:ok, pid} = Agent.start(Find3r.Utils, :addresses_for, [range]) 
    Agent.get_and_update(pid, fn(state) -> foo(state) end) |> loop(pid) 
    {:reply, :ok, :ok} 
    end 


    # Avoids an exception when the Agent runs out of addresses 
    defp foo([ip|rest]), do: {ip, rest} 
    defp foo(_),   do: {[], []} 

    defp loop(ip, pid) when is_tuple(ip) do 
    spawn(Find3r.Utils, :scan, [ip]) 
    Agent.get_and_update(pid, fn(state) -> foo(state) end) |> loop(pid) 
    end 
    defp loop(_, _), do: nil 


end 

该项目已移至GitHub
再次感谢O/

+3

请你提供的代码片段,并尝试你的问题归结到一些非常具体的 - 这样它更容易写一个有用的答案 –

+0

的问题很简单:我不知道如何使有限数量的的工作人员(例如[这里](https://git.yt/AnneGwenn/Find3r/src/master/lib/find3r/worker.ex))将清单的头部传递给Find3r。 Utils.scan/1'函数并将尾部返回存储IP地址列表的代理。 – Uniaika

+0

请在问题中发布代码,并尝试使问题自成一体,而无需关注外部链接,阅读评论等 –

回答

0

我设法弄清楚如何去做(我想这是怎么做到的)。

defmodule Find3r.Worker do 
use GenServer 
require Logger 

    def start_link, do: GenServer.start_link(__MODULE__, :ok, name: :worker) 

    def init(:ok) do 
    Logger.debug("Worker activated.") 
    {:ok, :ok} 
    end 

    def scan_range(range), do: GenServer.call(__MODULE__, {:scan_range, range}) 

    def handle_call({:scan_range, range}, _from, :ok) do 
    Logger.debug("Scanning #{range}") 
    {:ok, pid} = Agent.start(Find3r.Utils, :addresses_for, [range]) 
    Agent.get_and_update(pid, fn(state) -> foo(state) end) |> loop(pid) 
    {:reply, :ok, :ok} 
    end 


    # Avoids an exception when the Agent runs out of addresses 
    defp foo([ip|rest]), do: {ip, rest} 
    defp foo(_),   do: {[], []} 

    defp loop(ip, pid) when is_tuple(ip) do 
    spawn(Find3r.Utils, :scan, [ip]) 
    Agent.get_and_update(pid, fn(state) -> foo(state) end) |> loop(pid) 
    end 
    defp loop(_, _), do: nil 


end 
0

一个简单的(破解-ISH)的方式做什么[我觉得]你所描述:

defmodule MultiScanner do 
    def scan(range) do 
    main_proc = self 
    Enum.each(range, fn(ip) -> 
         spawn_link(fn -> 
         res = Find3r.Utils.scan(ip) 
         send main_proc, {:ip_results, ip, res} 
         end) 
        end) 
    ip_map = Enum.map(range, fn(ip) -> {ip, nil} end) 
      |> Enum.into(%{}) 
    wait_for_results(ip_map) 
    end 

    defp wait_for_results(ip_map, acc \\ %{}) 
    defp wait_for_results(ip_map, acc) when map_size(ip_map) == 0, do: acc 
    defp wait_for_results(ip_map, acc) do 
    receive do 
     {:ip_results, ip, res} -> 
     acc = Map.put(acc, ip, res) 
     ip_map = Map.delete(ip_map, ip) 
     wait_for_results(ip_map, acc) 
    end 
    end 
end 

这生成一个进程为每个IP地址,运行扫描,并将结果发送回调用进程,然后将结果折叠为ip =>结果的映射。

这种方法显然存在许多问题 - 最明显的是,您可能不希望所有您的扫描同时开始。

还有一堆的方法来解决这个问题,但除了像poolboy罐头的解决方案,如意见提出,或:gproc - 如果我要真正实现一个强大的解决方案,以这种方式,我可能会组建了一个监督树是这样的:

Scan.Supervisor 
    -ScanWorker.Supervisor (simple-one-for-one) 
     -ScanWorker (anon GenServer, executing a single scan) 
     -ScanWorker 
     ... 
    -ScanWorker.Manager (Named GenServer, coordinates the ScanWorkers) 

我的信封架构将有超过4个模块的后面,再加上顶级模块Scan举行的公共API。我也想象这需要一个小时左右的时间来充实,直到我不会尴尬地向同事展示它。

我开始为你画出来 - 但坦率地说,你的问题是模糊的,写得不好。你似乎没有多少时间写它,或者甚至打扰到校对它。我在这里放在一起的答案可能比我的时间更慷慨,而不是你的问题。我认为如果你花更多的时间和精力写下你的问题,你会发现更好的成就。

+0

嗨。首先,谢谢你的回答,克里斯。 我的问题写得不好,因为英文不是我的母语,我不能说我习惯用它的技术术语来表达我自己(以及我没有掌握所有概念的编程语言)。 但是,最近我发现了一种[解决方案](https://github.com/Annwenn/Find3r/blob/master/lib/find3r/worker.ex#L14-L19)。如果点击外部链接不会让你感到耻辱,请随时查看。 它使用一个代理,令人惊讶的是虚拟机处理一个/ 16非常好。 祝您有愉快的一天。 – Uniaika

+0

如果你找到了一个好的解决方案,你可能想把它写成答案,并接受它,以便其他人可以从你的研究中受益。很高兴你能找到一个可以接受的解决方案。 –

+0

是的,谢谢> _> – Uniaika