我正在制作一个多聊天应用程序,这里是code。在这个应用程序中,我制作了一个服务器,这里是代码:
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
我想当我在一个端口上启动一个节点时,另一个节点不能不连接到另一个端口上。这怎么可能呢?
1条答案
按热度按时间mqxuamgl1#
In linux, listening sockets are bound to any of the device's IP or all of them (1), usually the default being listening in all of them (the
0.0.0.0
ip). Once a process is listening in oneip:port
, no other socket is able to listen in the sameip:port
(2)(1) This is not entirely true, because you have network namespaces and the IP_FREEBIND option. (2) Again, not entirely true, you have the SO_REUSEPORT socket option.
So, in this case you have several options:
127.0.0.1
and127.0.0.2
Socket options are explained here
In Erlang, it seems that the relatively new low-level socket API has the
reuseport
option available, whereas, from the inet documentation (gen_tcp), it seems thatSO_REUSEPORT
is only available as araw
option.