Erlang 聊天室程序(十一) 主题房间之Supervisor引起的改造

       于由使用了Supervisor来管理当前所有的房间,每个房间都为单独的进程,所以要计对之前的chat_room.erl代码做相应的修改。

       具体包括以下几点:

       1.getPid/0  : 以前是由{local,?Module}房间进程来产生新的客户端进程。这次由于采用simple_one_to_one的启动方式,所以要重新指定客户端进程的产生方式(这里交由大厅来创建)

          所以修改chat_room进程的创建方法,房间名由外部传入,再根据房间名为每个chat_room进程命名。

start_link(Para)->
    #roominfo{name=Name,type=Type}=Para,
    gen_server:start_link({local,list_to_atom(Name)}, [Para],[]).

         再修改echatServer.erl,启动supervisor后创建大厅子进程

start()->
    %start supervisor
    room_manager:start_link([]),
    
    %add hall to supervisor
    Para=#roominfo{name="room-hall",type="public"},
    room_manager:startNewRoom(Para),
    
    chat_acceptor:start(3377),
    ok.

       可以看到,这里为大厅指定的进程名为"room-hall",所以下面修改getPid/0

getPid()->
    Id=id_generator:getnewid(client),
    Pid=gen_server:call(list_to_existing_atom("room-hall"),{getpid,Id}),
    io:format("id generated ~w~n",[Id]),
    #clientinfo{id=Id,pid=Pid}
.

       2. bindPid/2 : 这次就要指定客户端进程具体要添加到哪个房间中。 同时为了方便后面的操作,我们为chat_room.erl添加两个函数joinRoom/2 和 leaveRoom/2 让客户端通过这两个函数来进入和退出某个房间。

%joinroom using room-name  or room-Pid
joinRoom(RoomName,ClientInfo)  when is_list(RoomName)->
   gen_server:call(list_to_existing_atom(RoomName), {add_clientinfo,ClientInfo})
;
joinRoom(Ref,ClientInfo)->
   gen_server:call(Ref, {add_clientinfo,ClientInfo})
.

%leave Room,clean userinfo
leaveRoom(RoomName,ClientInfo)  when is_list(RoomName)->
    gen_server:call(list_to_existing_atom(RoomName), {remove_clientinfo,ClientInfo})
;
leaveRoom(Ref,ClientInfo)->
    gen_server:call(Ref, {remove_clientinfo,ClientInfo})
.

       在此基础上再修改bindPid/2 (第一次进入房间时默认为进入大厅)

bindPid(Record,Socket)->    
    io:format("binding socket...~n"),    
     case gen_tcp:controlling_process(Socket, Record#clientinfo.pid)  of
        {error,Reason}->
            io:format("binding socket...error~n");
        ok ->
            NewRec =#clientinfo{id=Record#clientinfo.id,socket=Socket,pid=Record#clientinfo.pid},
            %gen_server:call(list_to_existing_atom("room-hall"), {add_clientinfo,NewRec}),
            joinRoom("room-hall",NewRec),
            %then we send info to clientSession to update it's State (Socket info)
            Pid=Record#clientinfo.pid,
            Pid!{bind,Socket},
            io:format("clientBinded~n")
     end
.

      3.setUserInfo/1 的改造。整个系统中,用户信息可以通过两个地方获取:1用户进程绑定的PID,它是一个gen_server,用户信息保存于State中。2用户信息存在用户所在房间的clientManager管理的ets表中。要更新用户信息,这两个地方就都要更新。

      先修改chat_room.erl部分:

setUserInfo(RoomName,Message)  when is_list(RoomName)->
    gen_server:call(list_to_existing_atom(RoomName), {set_clientinfo,Message})
;
setUserInfo(Ref,Message)->
    gen_server:call(Ref, {set_clientinfo,Message})
.

     再修改客户端部分,由于所有接受到的消息都是交由message_router路由的,所以修改message_router.erl中的代码:

     Message消息需要在这里被解析为#clientinfo

routeMessage(Type,Sub,Message,State)->
        #clientinfo{pid=From}=State,
         case Type  of
        "msg"->
                 case Sub  of
                    "chat"->
                        io:format("message_router:route to chat_room:broadcast:~p~n",[Message]),
                        chat_room:broadCastMsg(Message);                    
                    _Els->
                        io:format("unkonw msssage subject:~p~n",[Sub])
                 end;
        "set"->
                 case Sub  of
                    "clientinfo"->
                        #message{content=Info,from=Key}=Message,
                        Rec =util_SetInfoParas:paraElements(Info),
                        From!{setinfo,Rec},
                        chat_room:setUserInfo(Message);

        4.broadCastMsg/1

%% broad CastMsg to all connected clientSessions
broadCastMsg(RoomName,Msg)  when is_list(RoomName)->
    gen_server:call(list_to_existing_atom(RoomName), {sendmsg,Msg})
;
broadCastMsg(Ref,Msg)->
    gen_server:call(Ref, {sendmsg,Msg})
.

       5.getMembers/1

getMembers(RoomName,Message)->
    gen_server:call(list_to_existing_atom(RoomName), {get_member,Message})
;
getMembers(Ref,Message)->
    gen_server:call(Ref, {get_member,Message})
.

 

你可能感兴趣的:(erlang)