2016-12-05 36 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之間的關係 –