【Erlang】基于gen_tcp的聊天室

本文介绍了一种使用Erlang语言通过TCP协议实现客户端与服务器之间的高效消息交互方法,包括如何在服务器端创建全局ETS表用于存储客户端ID与Socket,以及客户端如何建立连接并使用gen_tcp模块接收和发送信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

功能:

  • 服务端记录每一个客户端的ID和对应的Socket(用ets表)
  • 客户端根据ID与别的客户端交互
  • 客户端要开一个新的进程接收信息,用 gen_tcp:controlling_process(Socket1, Pid)监听
  • 客户端循环发送消息

代码:

-module(tcp).
-compile(export_all).
-import(ets,[insert_new/2]).

%服务端
start_parallel_server() ->
	%创建一个全局的ets表,存放客户端的id
	ets:new(id, [ordered_set, public, named_table, {write_concurrency, true}, {read_concurrency, true}]),
    
    case gen_tcp:listen(1234, [binary, {packet,0}, {active,true}]) of
        {ok, ListenSocket} ->
            spawn(fun()-> par_connect(ListenSocket) end);     
        {error, Reason} ->
            io:format("~p~n", [Reason])
    end.

par_connect(ListenSocket) ->
    case gen_tcp:accept(ListenSocket) of  
        {ok,Socket} ->
        	%每连接到一个客户端,把id插入到ets表中
        	case ets:last(id) of
        		'$end_of_table' ->
        			ets:insert(id, {1, Socket});
        		Other ->
        			ets:insert(id, {Other+1, Socket})
        	end,
            spawn(fun() -> par_connect(ListenSocket) end),   			     %每连接一个客户端都新开一个进程
            loop(Socket);
        {error, Reason} ->
            io:format("~p~n", [Reason])
    end.

loop(Socket) ->
    receive
        {tcp, Socket, Bin} ->
            [ID, Msg] = binary_to_term(Bin),
            io:format("Messages is ~p~n", [Msg]),
            [{Id, Socket1}] = ets:lookup(id,ID),
            gen_tcp:send(Socket1, term_to_binary(Msg)),
            loop(Socket);
        {tcp_closed, Socket} ->
            io:format("Server socket closed ~n")
    end.



%客户端
start_client() ->
    {ok, Socket1} = gen_tcp:connect("localhost", 1234, [binary, {packet,0}]),  %连接服务器
    %新建一个进程负责接收消息
    Pid = spawn(fun() -> loop1() end),
    %监听指定进程
    gen_tcp:controlling_process(Socket1, Pid),

    %负责发送信息
    sendMsg(Socket1).
    
loop1() ->
    	receive
        	{tcp, Socket, Bin} ->
	        	Res = binary_to_term(Bin),
	        	io:format("Receive massages = ~p~n", [Res]),
	        	loop1();
	    	{tcp_closed, Socket} ->
	        	io:format("Scoket is closed! ~n")
    	end.

sendMsg(Socket1) ->
 		I = io:get_line("id:"),
		M = io:get_line("say:"),
		{Ii, Info} = string:to_integer(I),

		gen_tcp:send(Socket1, term_to_binary([Ii, M])),
		sendMsg(Socket1).



效果:



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值