gpt4 book ai didi

elixir - 如何编辑回显服务器以允许多个客户端交换消息

转载 作者:行者123 更新时间:2023-12-03 19:05:16 25 4
gpt4 key购买 nike

我创建了一个没有客户端代码的服务器。我只需要在终端 telnet 127.0.0.1 4001 和另一个终端上输入 telnet 127.0.0.2 4001 所以当我在第一个终端上输入一条消息时,它会出现在同一个终端上,我知道这是一个回显服务器,我想要的如果可能的话,就是修改此代码,以便其他终端上的其他客户端可以接收到消息。这是回显服务器代码:

defmodule Multichat.Server do
require Logger

def accept(port) do
{:ok, socket} = :gen_tcp.listen(port, [:binary, packet: :line, active: false, 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} = Task.Supervisor.start_child(Multichat.Server.TaskSupervisor, fn -> serve(client) end)
:ok = :gen_tcp.controlling_process(client, pid)
loop_acceptor(socket)
end

defp serve(socket) do
socket
|> read_line()
|> write_line(socket)

serve(socket)
end

defp read_line(socket) do
{:ok, data} = :gen_tcp.recv(socket, 0)
data
end

defp write_line(line, socket) do
:gen_tcp.send(socket, line)
end
end

我应该更改什么,以便当我使用 telnet 打开许多客户端时,它们会收到来自彼此的消息

最佳答案

我认为实现此目的的最简单方法是将套接字设置为事件 模式,并在GenServer 中处理单个客户端的消息。然后,通过维护所有客户端处理程序的列表,您可以遍历该列表并向每个客户端发送消息。一个有效但不是很干净的版本:

defmodule Multichat.ClientConnection do
use GenServer

def start_link(socket), do: GenServer.start_link(__MODULE__, socket)

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

defmodule Multichat.Server do

# ...

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

在这里,我使用 DynamicSupervisor.which_children/1 来获取已启动的客户端处理程序的列表。为此目的使用 Registry 可能是更好的主意。

关于elixir - 如何编辑回显服务器以允许多个客户端交换消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63793389/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com