非同期メッセージパッシングというパラダイムのおかげで簡単に書けます。
こちらです!どんどん落書きしてください!
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、どっちも好きです!
魅力あふれるソースコードが激しい横スクロールで読みにくいです。
返信削除ですねー。Syntax Highlighterつかってみたものの、、、。
返信削除Githubへのリンク加えました。