如何在 Yaws 中处理与客户端关闭的 WebSocket?
我实现了一个简单的 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
更新的答案:
从 github commit 16834c(最终将成为 Yaws 1.93 的一部分)开始,当客户端发送
close
消息时,Yaws 会向您的 WebSockets 回调模块传递一个新的回调。回调为:其中
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: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}
whereCloseReason
is either the atomnormal
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 thatCloseReason
is unrelated to anyReason
value passed by the client. TechnicallyCloseReason
can also be any other Erlang term, in which case Yaws returns status 1000 and passes the term toerlang:exit/1
to exit the Erlang process handling the web socket, but based on RFC 6455 we suggest simply returning the atomnormal
forCloseReason
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 fromhandle_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 callthis._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 theonclose
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 callthis._ws.close()
in the client no matter what message the user enters, and in that case no alert foronclose
occurred. In this case, a check withlsof
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.