Egy kis Erlang mára

A sok actor-ozás után kedvet kaptam, hogy ismét elővegyem annak idején el se kezdett Erlang-tanulmányaimat, mert miért ne. Úgyhogy összeütöttem valamit, aminek nincs sok értelme.
Disclaimer: életem második Erlang kódja...


%% @author wachag
%% @doc A simple chat server


-module(server).

-export([main/0]).

main() ->
        {ok, ListenSocket} = gen_tcp:listen(1552, [list, {packet,0}, {active,false},{reuseaddr,true}]),
        Server=spawn(fun() -> serverLoop([]) end),
        acceptConnections(Server,ListenSocket,[]).

%% we accept client connections here
%% for each connection a new process is spawned, which will handle the client messages 
acceptConnections(Server,ListenSocket,Pids) ->
        {ok,Socket} = gen_tcp:accept(ListenSocket),
        Pid=spawn(fun() -> clientLaunch() end),
        gen_tcp:controlling_process(Socket,Pid),
        Server ! {newclient,Pid},
        Pid ! {take,Socket,Server},
        acceptConnections(Server,ListenSocket,Pids++[Pid]).

%% main loop of the server socket: broadcasts incoming client messages to the others
serverLoop(Clients) ->
        receive
                {newclient, ClientPid} -> io:format("Hello ~p~n",[ClientPid]),serverLoop(Clients++[ClientPid]);
                {delclient, ClientPid} -> io:format("Goodbye ~p~n",[ClientPid]),serverLoop(lists:delete(ClientPid,Clients));
                {broadcast,Pid, Data} -> lists:map(fun(C) -> C! {send,Data} end,lists:filter(fun(C) -> C /= Pid end,Clients)), io:format("Received ~p~n",[Data]),serverLoop(Clients)
        end.
%% to avoid race condition with gen_tcp:controlling_process(): wait until we can take the socket
clientLaunch() ->
        receive
                {take, Sck,Server} -> clientLoop(Sck,Server);
                _ -> clientLaunch()
        end.


%% main loop of the client socket: receives data and broadcast it to the others
clientLoop(Sock,Server) ->
        inet:setopts(Sock, [{active, once}]),
        receive
                {send,Data} -> gen_tcp:send(Sock, Data), clientLoop(Sock,Server);
                {tcp, Socket, Data} -> Server!{broadcast,self(),Data}, clientLoop(Socket,Server);
                {tcp_closed, _} -> io:format("Bye!\n"), Server ! {delclient, self()};
                {tcp_error, _,_} -> io:format("Error!\n"), Server ! {delclient, self()}
        end.

Hozzászólások

Ez egy chat szerver? Not bad, elég rövid a kód. :)