带有牛仔和 websocket 的 erlang 聊天室
Posted
技术标签:
【中文标题】带有牛仔和 websocket 的 erlang 聊天室【英文标题】:Chat room in erlang with cowboy and websocket 【发布时间】:2021-05-09 13:55:51 【问题描述】:我正在尝试使用牛仔 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.
【问题讨论】:
【参考方案1】:我不知道如何保存连接到 websocket 的套接字,所以我们 可以给他们发消息
在 erlang 中,gen_servers 可用于存储状态,因此您可以创建一个gen_server
,websocket 处理程序使用该gen_server
来保存客户端 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())
.
【讨论】:
您好,感谢您的回复。如果您能链接到任何用于构建基于牛仔/websockets 的聊天的资源,我将不胜感激。我对常规牛仔服务器非常熟悉。以上是关于带有牛仔和 websocket 的 erlang 聊天室的主要内容,如果未能解决你的问题,请参考以下文章
在牛仔 websocket 处理程序中使用 gproc 注册两个本地进程时出现问题
Joe 的 Erlang websocket 示例的 Python 示例