erlang写一个简单的聊天室

  • Post author:
  • Post category:其他


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 版权协议,转载请附上原文出处链接和本声明。