1,chat_server.erl
[code]
-module(chat_server).
-export([start/1]).
-define(TCP_OPTIONS, [list, {packet, 0}, {active, false}, {reuseaddr, true}]).
start(Port) ->
Pid = spawn(fun() -> manage_clients([]) end),
register(client_manager, Pid),
{ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
do_accept(LSocket).
do_accept(LSocket) ->
{ok, Socket} = gen_tcp:accept(LSocket),
spawn(fun() -> handle_client(Socket) end),
client_manager ! {connect, Socket},
do_accept(LSocket).
handle_client(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
client_manager ! {data, Data},
handle_client(Socket);
{error, closed} ->
client_manager ! {disconnect, Socket}
end.
manage_clients(Sockets) ->
receive
{connect, Socket} ->
io:fwrite("Socket connected: ~w~n", [Socket]),
NewSockets = [Socket | Sockets];
{disconnect, Socket} ->
io:fwrite("Socket disconnected: ~w~n", [Socket]),
NewSockets = lists:delete(Socket, Sockets);
{data, Data} ->
send_data(Sockets, Data),
NewSockets = Sockets
end,
manage_clients(NewSockets).
send_data(Sockets, Data) ->
SendData = fun(Socket) ->
gen_tcp:send(Socket, Data)
end,
lists:foreach(SendData, Sockets).
[/code]
server监听Socket连接,并群发消息到所有的client
2,chat_send_client.erl
[code]
-module(chat_send_client).
-export([start/2]).
start(IP, Port) ->
{ok, Socket} = gen_tcp:connect(IP, Port, [binary, {packet, 4}]),
talk(Socket).
talk(Socket) ->
Msg = io:get_line('Input you msg:'),
ok = gen_tcp:send(Socket, term_to_binary(Msg)),
talk(Socket).
[/code]
send_client用来启动一个client发消息的进程
3,chat_recv_client.erl
[code]
-module(chat_recv_client).
-export([start/2]).
start(IP, Port) ->
{ok, Socket} = gen_tcp:connect(IP, Port, [binary, {packet, 4}]),
recv_msg(Socket).
recv_msg(Socket) ->
receive
{tcp, Socket, Bin} ->
Msg = binary_to_term(Bin),
io:format("Received msg: ~p~n", [Msg]),
recv_msg(Socket)
end.
[/code]
recv_client用来在client端实时显示所有登录聊天室的client发送的消息
4,启动server
[code]
Eshell> chat_server:start(9999).
[/code]
5,启动send和recv两个client进程
[code]
$$ client1
Eshell> chat_send_client:start("localhost", 9999).
Eshell> chat_recv_client:start("localhost", 9999).
$$ client2
Eshell> chat_send_client:start("localhost", 9999).
Eshell> chat_recv_client:start("localhost", 9999).
[/code]
6,交互过程
[code]
%% client1/send
Input you msg:我囧
%% client2/send
Input you msg:你囧啥?
%% client1、2/recv
Received msg: "我囧\n"
Received msg: "你囧啥?\n"
[/code]
[code]
-module(chat_server).
-export([start/1]).
-define(TCP_OPTIONS, [list, {packet, 0}, {active, false}, {reuseaddr, true}]).
start(Port) ->
Pid = spawn(fun() -> manage_clients([]) end),
register(client_manager, Pid),
{ok, LSocket} = gen_tcp:listen(Port, ?TCP_OPTIONS),
do_accept(LSocket).
do_accept(LSocket) ->
{ok, Socket} = gen_tcp:accept(LSocket),
spawn(fun() -> handle_client(Socket) end),
client_manager ! {connect, Socket},
do_accept(LSocket).
handle_client(Socket) ->
case gen_tcp:recv(Socket, 0) of
{ok, Data} ->
client_manager ! {data, Data},
handle_client(Socket);
{error, closed} ->
client_manager ! {disconnect, Socket}
end.
manage_clients(Sockets) ->
receive
{connect, Socket} ->
io:fwrite("Socket connected: ~w~n", [Socket]),
NewSockets = [Socket | Sockets];
{disconnect, Socket} ->
io:fwrite("Socket disconnected: ~w~n", [Socket]),
NewSockets = lists:delete(Socket, Sockets);
{data, Data} ->
send_data(Sockets, Data),
NewSockets = Sockets
end,
manage_clients(NewSockets).
send_data(Sockets, Data) ->
SendData = fun(Socket) ->
gen_tcp:send(Socket, Data)
end,
lists:foreach(SendData, Sockets).
[/code]
server监听Socket连接,并群发消息到所有的client
2,chat_send_client.erl
[code]
-module(chat_send_client).
-export([start/2]).
start(IP, Port) ->
{ok, Socket} = gen_tcp:connect(IP, Port, [binary, {packet, 4}]),
talk(Socket).
talk(Socket) ->
Msg = io:get_line('Input you msg:'),
ok = gen_tcp:send(Socket, term_to_binary(Msg)),
talk(Socket).
[/code]
send_client用来启动一个client发消息的进程
3,chat_recv_client.erl
[code]
-module(chat_recv_client).
-export([start/2]).
start(IP, Port) ->
{ok, Socket} = gen_tcp:connect(IP, Port, [binary, {packet, 4}]),
recv_msg(Socket).
recv_msg(Socket) ->
receive
{tcp, Socket, Bin} ->
Msg = binary_to_term(Bin),
io:format("Received msg: ~p~n", [Msg]),
recv_msg(Socket)
end.
[/code]
recv_client用来在client端实时显示所有登录聊天室的client发送的消息
4,启动server
[code]
Eshell> chat_server:start(9999).
[/code]
5,启动send和recv两个client进程
[code]
$$ client1
Eshell> chat_send_client:start("localhost", 9999).
Eshell> chat_recv_client:start("localhost", 9999).
$$ client2
Eshell> chat_send_client:start("localhost", 9999).
Eshell> chat_recv_client:start("localhost", 9999).
[/code]
6,交互过程
[code]
%% client1/send
Input you msg:我囧
%% client2/send
Input you msg:你囧啥?
%% client1、2/recv
Received msg: "我囧\n"
Received msg: "你囧啥?\n"
[/code]