2016-12-05 48 views
0

我通常使用这种模式对于具有单个TCP资源进行交互,在active-mode从一个GenServer管理在活动模式的多个TCP连接

def connect(ip, port) do 
    t = System.system_time(1000) 
    case :gen_tcp.connect(ip, port, [:binary, active: :once, keepalive: true, nodelay: true]) do 
     {:ok, socket} -> 
     log "Connected to #{ip}:#{port} in #{System.system_time(1000) - t}ms" 
     socket 
     {:error, err} -> 
     log "Connect Error - #{ip}: #{port} [#{inspect err}]" 
     Process.send_after(self(), :retry_connect, 3000) 
     nil 
    end 
    end 

    def handle_info({:tcp, _, data}, s) do 
    s = proc_raw(s.extra <> data, %{s | extra: ""}) 

    :inet.setopts(s.socket, active: :once) 

    {:noreply, s} 
    end 

这如何被​​扩展以处理多个 TCP连接同样的GenServer

到目前为止,这在active-mode

更新

每个GenServer的主管下管理单个TCP套接字的伟大工程。另外,每个GenServer代表一个客户端,每个客户端可能有3-5个到某些外部资源的TCP连接。 TCP连接的

故障/复位预计不时,重新连接试图在每个故障,但主机GenServer不需要重新启动

+0

为什么你不想每个连接一个进程?隔离连接是有意义的,因为单个连接可能会关闭,并且不应该影响其他连接。 –

+0

每个GenServer用于单个客户端实例。每个客户端实例管理多达5个TCP连接到相同的TCP资源 –

+0

@MartinSvalin关闭或失败的TCP连接将被管理并重新启动,它不应该使进程崩溃,因为它是预期的状态 –

回答

2

虽然我同意@Onorio Catenacci认为多个GenServers可能是更好的选择。不过,我仍然会回答你问的问题。

传递给handle_info的元组的第二个位置是正在接收数据的套接字。因此,您已经知道它来自哪个套接字。

handle_info({:tcp, socket, data}, s) do 
    # do something with the socket here ... 
end 

我会怀疑需要,在保持所有打开的套接字的参考唯一的其他变化,这可以通过修改handle_call的连接功能,您GenServer的init功能是这样来完成:

def init(_) do 
    {:ok, []} 
end 

def handle_call({:connect, ip, port}, _from, sockets) do 
    s = connect(ip, port) 
    {:reply, :ok, [s|sockets]} 
end 

请注意,您可能还需要以类似的方式更改您的handle_call:retry_connect函数。

希望这会有所帮助。

+0

谢谢,我还没有意识到套接字也是以'handle_info({:tcp,socket,data},s)'的形式返回的' –

+0

对于独立模式,我目前每个连接使用一个名为GenServer。我期望运行多个GenServers,然后让每个Genserver管理几个TCP连接。 @ Onorio-Catenacci提出的建议在我的情况下并不理想 –

2

我建议你使用一个Supervisor而不是GenServer。监事可以让你自动重启除其他事项外一个失败的连接:

当事情失败了,你的第一反应可能是:“让我们拯救那些 错误”。但在Elixir中,我们避免了像其他语言中常见的那样拯救异常的防御性编程习惯。相反,我们 说“让它崩溃”。如果有一个错误导致我们的注册表崩溃,我们没有什么可担心的,因为我们将设置一个 主管,该主管将启动一个新的注册表副本。

我意识到上述文章正在讨论一个“注册表”,但概念是相同的。

我也意识到我的答案有点通用。但是,由于你的问题也很通用,所以我很难给你更具体的东西。如果你有更具体的问题,我建议你编辑你的问题,我们可以给你更具体的答案。

+0

每个GenServer是受监督的 –

+0

好吧,那么如果每个GenServer都受到监督,为什么你想让每个GenServer处理多个连接?只需启动更多的GenServers。我的意思是,如果在添加更多GenServers时存在一些限制,那么您需要将其添加到您的问题中,因为它好像是在试图解决一个不存在的问题。 –

+0

我已经用一些上下文更新了问题,给出了GenServer和Connections之间的关系 –