如何在 Yaws 中处理与客户端关闭的 WebSocket?

发布于 2025-01-04 09:18:54 字数 665 浏览 1 评论 0原文

我实现了一个简单的 appmod 来处理 WebSocket 并回显消息。但是我如何处理来自 JavaScript 客户端的 ws.close(); 呢?我尝试使用下面的代码,但是 handle_message({close, Reason}) 从未被调用,并且 ws.onclose = function(evt) {} 从未在JavaScript 客户端。

当我使用与 node.js websocket 交互的相同 JavaScript 客户端代码时,客户端在 ws.close(); 之后立即收到 onclose 事件。

这是我的简单 appmod 的代码:

-module(mywebsocket).
-export([handle_message/1]).

handle_message({text, Message}) ->
    {reply, {text, <<Message/binary>>}};

handle_message({close, Reason}) ->
    io:format("User closed websocket.~n", []),
    {close, normal}.

I have implemented a simple appmod that handle WebSockets and echo back the messages. But how do I handle an ws.close(); from the JavaScript client? I have tried with the code below, but handle_message({close, Reason}) is never called and ws.onclose = function(evt) {} is never executed on the JavaScript client.

When I use the same JavaScript client code interacting with a node.js websocket, the client receives an onclose event immediately after ws.close();.

Here is the code for my simple appmod:

-module(mywebsocket).
-export([handle_message/1]).

handle_message({text, Message}) ->
    {reply, {text, <<Message/binary>>}};

handle_message({close, Reason}) ->
    io:format("User closed websocket.~n", []),
    {close, normal}.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别在捏我脸啦 2025-01-11 09:18:54

更新的答案:

从 github commit 16834c(最终将成为 Yaws 1.93 的一部分)开始,当客户端发送 close 消息时,Yaws 会向您的 WebSockets 回调模块传递一个新的回调。回调为:

{close, Status, Reason}

其中 Status 是客户端发送的关闭状态,或者如果客户端不包含状态值,则为数值 1000(由 RFC 6455 指定用于正常关闭)。 Reason 是一个二进制文件,保存从客户端传递的任何可选原因字符串;如果客户端没有发送任何原因,它将是一个空的二进制文件。

close 消息的回调处理程序必须返回 {close, CloseReason},其中 CloseReason 是原子 normal正常关闭(导致状态代码 1000 返回给客户端)或 RFC 6455 允许的其他合法数字状态代码。请注意,CloseReason 与任何客户端传递的原因值。从技术上讲,CloseReason 也可以是任何其他 Erlang 术语,在这种情况下,Yaws 返回状态 1000 并将该术语传递给 erlang:exit/1 以退出处理 Web 套接字的 Erlang 进程,但根据 RFC 6455,我们建议在所有情况下都简单地为 CloseReason 返回原子 normal

原始答案,已被 Yaws github commit 16834c 废弃:

Yaws 永远不会将 {close, Reason} 消息传递给您的回调模块。相反,如果您的回调模块决定要关闭 ws 套接字,则 {close, Reason} 是来自 handle_message/1 的有效返回值。

我修改了 Yaws(版本 1.92)附带的 websockets_example.yaws 文件,以便在用户输入“bye”消息时在客户端中调用 this._ws.close()网页,并在 _onclose 函数中添加了一个警报,以显示 onclose 事件被触发。在这种情况下,发生警报,​​我相信是因为“再见”消息导致服务器显式关闭 ws 套接字。但随后我修改了示例,无论用户输入什么消息,都在客户端中调用 this._ws.close() ,在这种情况下,不会发生 onclose 警报。在本例中,使用 lsof 检查显示从浏览器到 Yaws 的 ws 连接仍然存在。

因此,目前我相信您遇到了一个错误,即 Yaws Websockets 支持未检测到客户端关闭并关闭其结束。我会看看是否可以修复它。

Updated answer:

As of github commit 16834c, which will eventually be part of Yaws 1.93, Yaws passes a new callback to your WebSockets callback module when the client sends a close message. The callback is:

{close, Status, Reason}

where Status is either the close status sent by the client, or the numerical value 1000 (specified by RFC 6455 for a normal close) if the client didn't include a status value. Reason is a binary holding any optional reason string passed from the client; it will be an empty binary if the client sent no reason.

Your callback handler for a close message MUST return {close, CloseReason} where CloseReason is either the atom normal for a normal close (which results in the status code 1000 being returned to the client) or another legal numerical status code allowed by RFC 6455. Note that CloseReason is unrelated to any Reason value passed by the client. Technically CloseReason can also be any other Erlang term, in which case Yaws returns status 1000 and passes the term to erlang:exit/1 to exit the Erlang process handling the web socket, but based on RFC 6455 we suggest simply returning the atom normal for CloseReason in all cases.

Original answer, obsoleted by Yaws github commit 16834c:

Yaws never passes a {close, Reason} message to your callback module. Rather, {close, Reason} is a valid return value from handle_message/1 should your callback module decide it wants to close the ws socket.

I modified the websockets_example.yaws file shipped with Yaws (version 1.92) to call this._ws.close() in the client if the user enters the "bye" message on the web page, and added an alert to the _onclose function to show that the onclose event is triggered. In this case the alert occurred, I believe because the "bye" message causes the server to close the ws socket explicitly. But I then modified the example to call this._ws.close() in the client no matter what message the user enters, and in that case no alert for onclose occurred. In this case, a check with lsof showed the ws connection from the browser to Yaws was still present.

So, for now I believe you've hit a bug where the Yaws websockets support isn't detecting the client close and closing its end. I'll see if I can fix it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文