websocket接続を受け取るws_handlerがあります。Cowboy Websocketハンドラの状態を更新すると、クラッシュしたりサイレントに無視されます。
このプロセスは、ログインするために<<"h
で始まる入力を待ちます。
それは、デフォルトのWebSocketの状態、(現在のPIDを参照して起動され)プレーヤプロセスID、および送信トレイメッセージ、 `< < "turn1" >>
websocket_handle({text, <<"h", Name/binary>>}, State) ->
{ok, PID} = player:go(self(), <<"profiledata", Name/binary>>),
erlang:start_timer(1000, self(), <<"Hello!">>),
{reply, {text, <<"You joined, ", Name/binary>>}, {State, PID, <<"turn1">>}};
Iを節約しますこの別個のプレーヤープロセスからのデータフローを制御したい場合、私のwebsocketハンドラにメッセージを取り出して、Outbox
要素を介してそのクライアントに渡すようにします。
だから私は手動でメッセージトリガするには、これを追加します。私はこれが呼び出されることを期待戻るws_handlerで
handle_call(myscreen, _, {WS, Profile, Cab}) ->
gen_server:cast(WS, myscreenupdate),
{reply, ok, {WS, Profile, Cab}};
、
websocket_handle({text, <<"myscreen">>}, S = {_, P, _}) ->
gen_server:call(P, myscreen),
{ok, S};
とplayer.erl中を:
websocket_info(myscreenupdate, State = {St,P, _}) ->
{reply, {text, <<"My screen update">>}, {St, P, <<"turn2">>}};
私のブラウザのwebsocket出力は、の代わりにturn1
を連続して印刷します。
gen_server:call
をplayer.erl
に入れてみましたが、タイムアウトが発生しました。私はws_handler
でwebsocket_handle
の{reply
タプルのWebSocketに返信することになっているので、これがあると思います..しかし、それが本当だったら、私は、データが更新されることを期待したい:
websocket_info(myscreenupdate, State = {St,P, _}) ->
{reply, {text, <<"My screen update">>}, {St, P, <<"turn2">>}};
だから、私はここで何が起きているのかは不明です。
Playerプロセスから状態を更新し、WebSocketハンドラでその状態を取得して接続に送信するにはどうすればよいですか?
ws_handler.erl:
-module(ws_handler).
-export([init/2]).
-export([websocket_init/1]).
-export([websocket_handle/2]).
-export([websocket_info/2]).
init(Req, Opts) ->
{cowboy_websocket, Req, Opts}.
websocket_init(State) ->
{ok, State}.
websocket_handle({text, <<"h", Name/binary>>}, State) ->
{ok, PID} = player:go(self(), <<"profiledata", Name/binary>>),
erlang:start_timer(1000, self(), <<"Hello!">>),
{reply, {text, <<"You joined, ", Name/binary>>}, {State, PID, <<"turn1">>}};
websocket_handle({text, <<"myscreen">>}, S = {_, P, _}) ->
gen_server:call(P, myscreen),
{ok, S};
websocket_handle({text, <<"auth", Auth/binary>>}, S = {_St, P, _}) ->
case s:s(P, Auth) of
{ok, Valid} -> {reply, {text, << "Authorized">>}, S};
_ -> {reply, {text, <<"Error">>}, S}
end;
websocket_handle({text, Msg}, S = {_St, P, Outbox}) ->
{reply, {text, Outbox}, S};
websocket_handle(_Data, State) ->
{ok, State}.
websocket_info(myscreenupdate, State = {St,P, _}) ->
{reply, {text, <<"My screen update">>}, {St, P, <<"turn2">>}};
websocket_info({timeout, _Ref, _Ignored}, State = {_, P, Outbox}) ->
erlang:start_timer(1000, self(), <<"This is ignored">>),
Msg = Outbox,
{reply, {text, Msg}, State};
websocket_info(_Info, State) ->
{ok, State}.
player.erl:
-module(player).
-compile(export_all).
handle_call(myscreen, _, {WS, Profile, Cab}) ->
gen_server:cast(WS, myscreenupdate),
{reply, ok, {WS, Profile, Cab}};
handle_call(get_profile, _, State = {_WSPID, Profile, _}) ->
{reply, Profile, State}.
init([WSPID, Profile]) ->
{ok, {WSPID, Profile, null}};
init([WSPID, Profile, CabinetPID]) ->
{ok, {WSPID, Profile, CabinetPID}}.
go(WSPID, Profile, CabinetPID) ->
gen_server:start_link(?MODULE, [WSPID, Profile, CabinetPID], []).
go(WSPID, Profile) ->
gen_server:start_link(?MODULE, [WSPID, Profile], []).
ここで役立つ情報があれば、https://github.com/7stud/Programming-Erlang-Exercises-Solutions-Answers/blob/master/Chapter%2018/simple_exampleをご覧ください。md – 7stud