websocket - erlang 中带有牛仔和 websocket 的聊天室

标签 websocket erlang cowboy

我正在尝试使用牛仔 websocket 处理程序创建一个聊天室。 我希望来自每个套接字的消息也能转发到其他套接字,就像聊天组一样。 我不知道如何实现这个? 我不知道如何保存连接到 websocket 的套接字,以便我们可以向它们发送消息。 我有一个牛仔管理员:

-module(chat_conn).

-export([ init/2
    , websocket_init/1
    , websocket_handle/2
    , websocket_info/2
    , terminate/3
    ]).

-include("chat.hrl").

init(Req, [WsConnIdleTimeout]) ->
    ?LOG_DEBUG("[CHAT-CONN] New HTTP Request on: /api , Pid: ~p", [self()]),
    WsOpts = #{idle_timeout => WsConnIdleTimeout},
    State = #{counter => 0},
    {cowboy_websocket, Req, State, WsOpts}.

websocket_init(State0) ->
    ?LOG_DEBUG("[FOOZI-CONN] HTTP Upgraded to WebSocketm pid: ~p", [self()]),
    NewState = State0,
    {ok, NewState}.

websocket_handle({text, PlainRequest}, #{counter := Counter0} = State) ->
    ?LOG_DEBUG("[HIGGS-CONN] Receive New Message: ~p, Pid: ~p" , [PlainRequest, self()]),
    NewCounter = Counter0 + 1,
    Reply = list_to_binary("Counter is: " ++ integer_to_list(NewCounter)),
    NewState = #{counter => NewCounter},
    {reply, {text, Reply}, NewState};
    %{ok, State};
websocket_handle(Frame, State) ->
    ?LOG_INFO("[HIGGS-CONN] Invalid Frame => ~p", [Frame]),
    {stop, State}.

websocket_info(Message, State) ->
    ?LOG_INFO("[CONN-INFO] Unhandled message! => Message: ~p", [Message]),
    {reply, {text, list_to_binary(Message)}, State}.
    %{ok, State}.

terminate(Reason, _, State) ->
    ?LOG_INFO("[CONN-TERMINATE] Terminated! => Pid: ~p, Reason: ~p, State: ~p", [self(), Reason, State]),
    ok.

最佳答案

I don't know how to save sockets that are connected to websocket so we can send messages to them

在erlang中,gen_servers可用于存储状态,因此您可以创建一个gen_server,websocket处理程序使用它来保存客户端pid。当客户端使用特定路由向您的牛仔服务器发送“开始聊天”消息时,将调用关联的 websocket 处理程序。在该处理程序中,self() 将是该客户端的 websocket 进程的 pid。您可以通过调用 gen_server:cast(chat_room, {arrive, self()}) 将该 pid 保存在 gen_server 中,然后再调用 chat_room:handle_cast() 将 pid 添加到存储在 State 变量中的 pid 列表中。

当牛仔服务器收到来自客户端浏览器的聊天消息时,客户端的 websocket 进程将处理该消息,并且在相应的 websocket 处理程序中,您可以查询 gen_server 来获取 pid 列表对于连接的客户端。然后您可以使用 ! 向每个人发送消息。反过来,每个客户端的 websocket_info() 处理程序将处理该消息,它可以通过返回以下内容通过 websocket 将消息转发回客户端:{reply, {text, Text}, State}.

对于您的 gen_server,您还需要实现一个 leave() 函数,相应的 websocket 处理程序将调用该函数来更新存储在 >gen_server,例如gen_server:cast(chat_room, {leave, self()})

关于websocket - erlang 中带有牛仔和 websocket 的聊天室,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66059636/

相关文章:

Qt websocket 服务器示例不起作用

erlang - erlang的 "monitor"给出了什么保证?

ssl - 如何使用 Erlang 发出 HTTPS 请求?

http - Erlang 停止应用程序不会结束所有进程?

erlang - 是否建议在应用程序主管树中添加牛仔?

android - 通过 xmpp 或 websocket 进行即时消息传递

c++ - 如何处理多个 websocket++ 选项卡/窗口?

file-upload - socket.io 与 ajax 上传文件的 +/- 是什么?

string - erlang中的驼峰式程序

javascript - 更改脚本文件时必须重建 Erlang 项目