问题
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}.
回答1:
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.
来源:https://stackoverflow.com/questions/9222786/how-do-i-handle-a-websocket-close-from-the-client-in-yaws