如何禁用两个节点在同一端口上连接



我正在制作一个多帽应用程序,下面是代码。在这个应用程序中,我制作了一个服务器,下面是代码:

defmodule Multichat.Server do
require Logger
def accept(port) do
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: :line, active: true, reuseaddr: true])
Logger.info "Accepting connections on port #{port}"
loop_acceptor(socket)
end
defp loop_acceptor(socket) do
{:ok, client} = :gen_tcp.accept(socket)
{:ok, pid} = DynamicSupervisor.start_child(Multichat.Server.ConnectionSupervisor, {Multichat.ClientConnection, client})
:ok = :gen_tcp.controlling_process(client, pid)
loop_acceptor(socket)
end
end

你可以在代码中看到一个客户端部分:

defmodule Multichat.ClientConnection do
use GenServer
def start_link(socket), do: GenServer.start_link(__MODULE__, socket)
def init(init_arg) do
{:ok, init_arg}
end
def handle_call({:send, message}, _from, socket) do
:gen_tcp.send(socket, message)
{:reply, :ok, socket}
end
def handle_info({:tcp, _socket, message}, socket) do
for {_, pid, _, _} <- DynamicSupervisor.which_children(Multichat.Server.ConnectionSupervisor) do
if pid != self() do
GenServer.call(pid, {:send, message})
end
end
{:noreply, socket}
end
end

我希望当我在一个端口上启动一个节点时,另一个节点只能连接到另一个端口。这怎么可能?

在linux中,侦听套接字绑定到设备的任何IP或所有IP(1(,通常默认为侦听所有IP(0.0.0.0IP(。一旦进程在一个ip:port中侦听,则没有其他套接字能够在同一ip:port(2(中侦听

(1( 这并不完全正确,因为您有网络名称空间和IP_FREEBIND选项。(2( 同样,也不完全正确,您有SO_REUSEPORT套接字选项。

因此,在这种情况下,您有几个选项:

  1. 为每个要本地启动的节点设置不同的端口,例如,使用环境变量
  2. 在开发过程中监听每个节点的不同IP,例如127.0.0.1127.0.0.2
  3. 在侦听套接字中设置SO_REUSEPORT选项
  4. 使用docker或其他容器/命名空间技术可以在不同的网络命名空间中启动不同的节点

这里解释了套接字选项
在Erlang中,相对较新的低级套接字API似乎有reuseport选项可用,而从inet文档(gen_tcp(来看,SO_REUSEPORT似乎只作为raw选项可用。

最新更新