-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchat_server.erl
58 lines (53 loc) · 2.19 KB
/
chat_server.erl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
-module(chat_server).
-export([server/0]).
server() ->
{ok, LSock} = gen_tcp:listen(5678, [binary, {packet, 0},
{active, false}]),
ConnectionManager = self(),
spawn(fun() -> new_connections(ConnectionManager, LSock) end),
manage_connections([]),
ok = gen_tcp:close(LSock).
new_connections(ConnectionManager, LSock) ->
case gen_tcp:accept(LSock) of
{ok, Sock} ->
ConnectionManager ! {add_sock, Sock},
new_connections(ConnectionManager, LSock);
{error, closed} -> ok
end.
handle_connection(ConnectionManager, MySock, Accum) ->
case gen_tcp:recv(MySock, 0) of
{ok, B} ->
case binary:split(B, <<"\n">>) of
[MsgEnd|Next] ->
Msg = binary_to_list(list_to_binary([Accum, MsgEnd])),
case Msg of
"/kill" ->
ConnectionManager ! die;
_ ->
ConnectionManager ! {send_msg, self(), MySock, Msg},
handle_connection(ConnectionManager, MySock, [Next])
end;
_ ->
handle_connection(ConnectionManager, MySock, [Accum, B])
end;
{error, closed} ->
ConnectionManager ! {remove_sock, self(), MySock}
end.
send(FormattedMsg, SenderSock, Socks) ->
Recipients = lists:delete(SenderSock, Socks),
lists:map(fun(Sock) -> gen_tcp:send(Sock, FormattedMsg) end, Recipients).
manage_connections(Socks) ->
receive
{add_sock, Sock} ->
ConnectionManager = self(),
Joiner = spawn(fun() -> handle_connection(ConnectionManager, Sock, []) end),
send(io_lib:format("~p joins", [Joiner]), Sock, Socks),
manage_connections([Sock|Socks]);
{remove_sock, Leaver, Sock} ->
send(io_lib:format("~p leaves", [Leaver]), Sock, Socks),
manage_connections(lists:delete(Sock, Socks));
{send_msg, Sender, SenderSock, Msg} ->
send(io_lib:format("~p: ~p", [Sender, Msg]), SenderSock, Socks),
manage_connections(Socks);
die -> ok
end.