1、chat_server.erl
-module(chat_server).
-export([start_server/0, wait_a_client/1, loop/1, all_send/1]).
start_server() ->
ets:new(chat_ets,[ordered_set, public, named_table, {write_concurrency, true}, {read_concurrency, true}]),%初始化一个表
case gen_tcp:listen(1234, [binary, {packet,0}, {active,true}]) of
{ok, Listen} ->
spawn(fun() -> wait_a_client(Listen) end);
{error, Msg} ->
io:format("~p~n",[Msg])
end.
wait_a_client(Listen) ->
case gen_tcp:accept(Listen) of%等待一个连接
{ok, Socket} ->
case ets:last(chat_ets) of
'$end_of_table' ->
ets:insert(chat_ets,{1,Socket}), %插入所有人的ID和Socket
gen_tcp:send(Socket,term_to_binary(1));%发送
Other ->
ets:insert(chat_ets,{Other+1,Socket}),
gen_tcp:send(Socket,term_to_binary(Other+1))
end,
spawn(fun() -> wait_a_client(Listen) end),%重开一个进程来绑定socket
loop(Socket);
{error, Msg} ->
io:format("~p~n",[Msg])
end.
loop(Socket) ->
receive
{tcp, Socket, Bin} ->
[ID, Msg] = binary_to_term(Bin),
case ID of
0 -> %若ID为0,则发送给所有人
chat_server:all_send(Msg),
loop(Socket);
_ -> %发送给特定ID的人
[{ID,SocketNum}] = ets:lookup(chat_ets,ID),
gen_tcp:send(SocketNum,term_to_binary(Msg)),
loop(Socket)
end;
{tcp_closed, Socket} ->
io:format("Server socket closed ~n")
end.
all_send(Msg) ->
[gen_tcp:send(Socket,term_to_binary(Msg))|| {P,Socket}<-ets:tab2list(chat_ets)].
2、chat_client.erl
-module(chat_client).
-export([my_client/0, loop/0, send_msg/1]).
my_client() ->
ets:new(name,[ordered_set, public, named_table, {write_concurrency, true}, {read_concurrency, true}]),
{ok, Socket} = gen_tcp:connect("localhost", 1234, [binary, {packet,0}]),
receive
{tcp,_From,ID} ->
ets:insert(name,{Socket,binary_to_term(ID)}),
io:format("You User_ID is ~p~n",[binary_to_term(ID)])
after 50000 ->
io:format("time out~n")
end,
Pid = spawn(fun() -> loop() end),
gen_tcp:controlling_process(Socket, Pid),%发送给这个Socket的信息就相当于发送到绑定的进程Pid
send_msg(Socket).
loop() ->
receive
{tcp,Socket,Msg} ->
io:format("~p~n",[binary_to_term(Msg)]),
loop();
{tcp_closed, Socket} ->
io:format("Scoket is closed! ~n")
end.
send_msg(Socket) ->
ID = io:get_line("ID:"),%输入要发送给谁的账号ID
Msg = io:get_line("msg:"),%输入要发送给谁的信息
[{_Temp,UID}] = ets:lookup(name,Socket),%获取自己的账号ID
Msg1 = integer_to_list(UID)++" say to you "++Msg,
{Ii, Info} = string:to_integer(ID),%获取输入的ID
gen_tcp:send(Socket,term_to_binary([Ii,Msg1])),
send_msg(Socket).
3、运行截图
(1)先开启两个cmd,在其中一个先编译。然后输入命令chat_server:start_server().运行聊天服务器,再输入命令chat_client:my_client().运行客户端,得到自己的账号ID。
(2)在另一个cmd运行chat_client:my_client().命令,也会得到另一个客户端的账号ID。
(3)然后在出现的ID:中输入你想和ID为什么的用户发送信息,随后在msg:输入要发送的信息即可。
(4)ID:输入0,则发送给所有人,否则发送给特定用户。
版权声明:本文为weixin_44997483原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。