erlang,socket简单实现多人聊天室

本文介绍了如何使用Erlang构建一个简单的多人聊天室。该聊天室实现了用户登录、聊天和退出功能,用户数据存储在ETS中,并能统计在线用户数。文章提供了服务端和客户端的基本代码框架,适合初学者参考。
摘要由CSDN通过智能技术生成

        菜鸟一枚,老大说要做个socket聊天室,用socket实现,所以就网上一搜基本都没什么资料,这里贡献一篇我自己写的很简陋的多人聊天室,有不对的地方,多多指出,谢谢。

  1.  基本要求:

   1. 写一个支持多人在线的socket聊天服务器和客户端,需要实现以下功能:
   a. 用户登录,用户管理相关的功能无需实现,手工构造几个用户数据就可以了;
   b. 实现用户登录,聊天和退出功能。用户数据中需要记录登录次数和聊天次数;
   c. 能够统计当前在线用户数;
   d. 用户数据存储在ets中;
   e. 定义服务端和客户的端通讯协议;

   %% 用户数据结构:
-record(user, {
        id      %% 用户ID
        ,name    %% 用户名称
        ,passwd %% 用户登录密码
        ,login_times %% 登录次数
        ,chat_times  %% 聊天次数
        ,last_login  %% 最后一次登录时间
        ,state  %% 登录状态  0 未登录  1已登录
    }

).

  服务端代码:

-module(server_example).
%-export([start/0,initialize_ets/0,info_lookup/1,loop/2,info_update/3,init/1,handle_call/3,terminate/2]).
%-import(counter,[start/1,add/1,value/1,decrease/1,log_add/1,chat_add/1]).
%-import(my_fsm,[start_count/0,count/1]).
-compile(export_all).
-include("user_info.hrl").
-define(SERVER,?MODULE).

start() ->
    gen_server:start_link({local,?SERVER},?MODULE,[],[]).

init([]) ->
    initialize_ets(),
    start_parallel_server(), 
    {ok,ets:new(mysocket,[public,named_table])}.





%开启服务器
start_parallel_server() ->
    {ok,Listen} = gen_tcp:listen(2345,[binary,{packet,0},{reuseaddr,true},{active,true}]),
    spawn(fun() -> per_connect(Listen) end).

%每次绑定一个当前Socket后再分裂一个新的服务端进程,再接收新的请求
per_connect(Listen) ->
    {ok,Socket} = gen_tcp:accept(Listen),
    spawn(fun() -> per_connect(Listen) end),
    loop(Socket).




%初始化ets
initialize_ets() ->
    ets:new(test,[set,public,named_table,{keypos,#user.name}]),
    ets:insert(test,#user{id=01,name="carlos",passwd="123",login_times=0,chat_times=0,last_login={},state=0}),
    ets:insert(test,#user{id=02,name="qiqi",passwd="123",login_times=0,chat_times=0,last_login={},state=0}),
    ets:insert(test,#user{id=03,name="cym",passwd="123",login_times=0,chat_times=0,last_login={},state=0}).

%查询ets
info_lookup(Key) ->
    %返回值是一个元组
    ets:lookup(test,Key).

%修改ets信息
info_update(Key,Pos,Update) ->
    ets:update_element(test,Key,{Pos,Update}).
 


%<<-------------------------回调函数----------------------------->>
%登录的时候添加socket
handle_call({addSocket,UserName,Socket},_From,Tab) ->
     Reply =   case ets:lookup(Tab,UserName) of
         	 [{UserName,Socket}] -> have_socket;

         	 []  ->  ets:insert(Tab,{UserName,Socket})
         end,  %这里是顺序结构,所以用逗号
         io:format("Tab ~p~n",[Tab]),
        % io:format("mysocket ~p~n",[ets:i(Tab)]),
     {reply,Reply,Tab};

%退出的时候,删除socket
handle_call({deleteSocket,UserName,Socket},_From,Tab) ->
     Reply =   case ets:lookup(Tab,UserName) of
         	 [{UserName,Socket}] -> ets:delete(Tab,UserName);

         	 []  ->   io:format("no exist this  socket ~p~n",[Socket])
         end,  %这里是顺序结构,所以用逗号
        
        % io:format("mysocket ~p~n",[ets:i(Tab)]),
     {reply,Reply,Tab};

%用户在线个数
handle_call({userNumber},_From,Tab) ->
 		 Socketlist = ets:tab2list(Tab),
         io:format("~p user online~n",[length(Socketlist)]),
     {reply,[],Tab};

%广播信息
handle_call({sendAllMessage,Name,Msg},_From,Tab) ->
            %Socketlist = [{UserName,Socket,Name,Msg}||{UserName,Socket} <- ets:tab2list(Tab)],  不用推导了
           Socketlist =[{UserName,Socket}||{UserName,Socket} <- ets:tab2list(Tab),UserName =/= Name],
           io:format("list ~p~n",[Socketlist]),

           lists:foreach(
           	   fun({UserNa
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值