拙作の
erlang_websocket_serverを用いて、
Canvas共有をErlangに移植しました。
非同期メッセージパッシングというパラダイムのおかげで簡単に書けます。
こちらです!どんどん落書きしてください!
http://etsukata.com/erl/cvws.html
ChromeおよびSafariで動作確認しています。複数のウインドウを立ち上げて描いてみてください。
クライアントサイドのコードは
Node.js版と全く一緒です。
サーバーサイドのコードを以下に掲載します。
githubでお読みになると、横スクロールがなくて見やすいです。
https://github.com/Etsukata/erlang_websocket_server/blob/master/example/canvas_sharing_handler.erl
-module(canvas_sharing_handler).
-import(websocket_server, [unicast/2, broadcast/2, sendall/1]).
-compile(export_all).
go() -> websocket_server:start("etsukata.com", 9000, ?MODULE, canvas_sharing_handler, [[],[]]).
canvas_sharing_handler(IDList, PointList) ->
receive
{open, ConnectionID} ->
broadcast("@NC:" ++ ConnectionID, ConnectionID),
unicast("@ID:" ++ ConnectionID, ConnectionID),
StrIDList = lists:foldr(fun(X, Xs) -> X ++ "," ++ Xs end, "", IDList),
Str = case StrIDList of
[] -> [];
_Any -> lists:sublist(StrIDList, length(StrIDList) -1)
end,
unicast("@PT:" ++ Str, ConnectionID),
lists:foreach(fun(X) -> unicast(X, ConnectionID) end, lists:reverse(PointList)),
canvas_sharing_handler([ConnectionID|IDList], PointList);
{message, Data, ConnectionID} ->
case lists:member($@, Data) of
true ->
case string:substr(Data, 1, 3) of
"@CU" ->
broadcast(Data, ConnectionID),
canvas_sharing_handler(IDList, []);
_Any ->
canvas_sharing_handler(IDList, PointList)
end;
false ->
broadcast(Data, ConnectionID),
canvas_sharing_handler(IDList, [Data|PointList])
end;
{closed, ConnectionID} ->
broadcast("@CL:" ++ ConnectionID, ConnectionID),
canvas_sharing_handler(lists:delete(ConnectionID,IDList), PointList);
Any ->
io:format("Any:~w~n", [Any]),
canvas_sharing_handler(IDList, PointList)
end.
Node.js版のソースコードとほとんど長さは変わっていません。
Node.jsのスピード感のある開発も楽しいです。しかしErlangのメッセージパッシングで考えたほうがほうが単純に物事を捉えることができ、これもまた楽しいのです。僕はNode.jsとErlang、どっちも好きです!