zoukankan      html  css  js  c++  java
  • Erlang 聊天室程序(六) 设置客户端程序2

               上篇开了个头编写了基本的框架,这次连同客户端服务器端代码一起完善下。

               首先修改客户端代码:

               之前在数据交换部分,客户端中定义了一个Message bean类,里面包含了发送一条消息所需要的基本信息,包括id、type、subject、from、to、content等。但这里的

    content是一个String 类型,如果要表示更复杂的消息就不太适用了。

               由于所有的消息id、type、subject、from、to 这几个成员的类型是确定的,对应的操作方法也是固定的,所以我们抽象出一个抽象类:Packet 用来表示交互中的所有消息:

    Packet.java:

           与之前不同的是这次将Bean解析为JSON String的任务交给Bean本身。可以看到以上代码中并没有定义content的实现,所以具体的消息可根据自身需要来定制。

           根据这个思想,改造普通消息类Message:              再修改下发送部分的代码,直接调用对象的toString()方法:


             新建一个类ClientInfo 表示客户端要设置的信息:


                 新建设置客户端消息类:SetClientInfo继承Packet类


               可以看到这里将content 设置为了刚才的ClientInfo 对象。

               下面修改服务器端:

               先要去掉JSON数据解析时的is_binary判断,因为以后发送的消息content里不一定就是binary了。


                再修改client_manager.erl 中更改客户端信息部分的代码,将content中的json数据转成#clientinfo,再更新到数据表中去。

                为此新建一个专门的模块util_SetInfoParas.erl处理setClientInfo消息:


               接着在更新数据库前调用以上代码:

               client_manager.erl:

                  更新成功后,会将此消息广播给所有的在线用户:

    chat_room.erl


          最后需要修改util_MessageParas.erl中的JSON编码部分,判断如果要发送给客户端的Message消息内容是list的话才转成相应的字符串。


            再修改客户端收到消息后的解析代码:


               测试结果如下:



            另外,既然能够设置客户端的昵称了,那么就再实现下发消息时from的替换吧:

    先为client_manager添加获取客户端昵称功能,获取不到或undfined就取默认的:

    getNick(Key)->
        case ets:lookup(clientinfo, Key) of
            [Record]->
                #clientinfo{nick=Nick}=Record,
                case Nick of
                    undefined ->
                        "client"++integer_to_list(Key);
                    Nick->
                         Nick
                end;
            []->
                "client"++integer_to_list(Key)
        end
    .

       再修改设置个人信息后的通知消息:

    handle_call({set_clientinfo,Message},From,State)->
        %we can send result message to client
        %or send a broadcast message to all client 
        #message{from=Id}=Message,
        [Client]=client_manager:getClient(Id),
        #clientinfo{pid=Pid}=Client,
        TheNick=client_manager:getNick(Id),    
        case client_manager:updateClient(Message)of
            {ok,Rec}->            
                #clientinfo{nick=Nick}=Rec,            
                %Content=["client",integer_to_list(Id),"has change nickname:"|Nick],
                %[Cont]=["client"|integer_to_list(Id)],
                %io:format("Cont is:~p~n",[Cont]),
                %[Cont1]=[Cont|"has change nickname:"],
                %io:format("Cont1 is:~p~n",[Cont1]),
                %[Content]=[Cont1|Nick],
                %io:format("Content is:~p~n",[Content]),
                
                Pid!{setinfo,Rec},                    
                {Content}={TheNick ++ " has change nickname:" ++ Nick},
                   NewMessage=#message{id="0",
                                 from=Id,
                                 to="",
                                 content=Content,
                                 type="msg",
                                 subject="chat",
                                 time=Message#message.time},
                io:format("Notice Message is:~p~n",[NewMessage]),
                sendMsg(NewMessage,[]);
            {false,Rec}->
                ok
        end,
        {reply,ok,State}
    .

        在修改client_session中下发时的from:

    handle_info({dwmsg,Message},State)->
        %here we should set from back
        io:format("client_session dwmsg state is ~p~n",[State]),
        #message{from=Id}=Message,
        Nick=client_manager:getNick(Id),    
        NewMessage =Message#message{from=Nick},
        JSON=util_MessageParas:paraseEncode(NewMessage),
        io:format("client_session dwmsg recived ~p~n",[JSON]),
        case gen_tcp:send(State#clientinfo.socket, JSON)of
            ok->
                io:format("client_session dwmsg sended ~n");
            {error,Reason}->    
                io:format("client_session dwmsg sended error ~p ~n",Reason)
        end,
        {noreply,State};

    测试效果如下:

     

  • 相关阅读:
    自动从vss下载代码并编译的脚本
    自动执行Sql脚本的批处理
    编译 SharpDevelop2.2源码 经过
    .net框架源代码批量下载器使用方法
    sql server 解决孤立用户问题
    元数据学习分享
    SQL注入攻击的原理及其防范措施(转)
    .Net Remoting和Web Service浅析(转)
    usercontrol 和 page 的继承
    如何提高页面现实速度
  • 原文地址:https://www.cnblogs.com/yjl49/p/2375600.html
Copyright © 2011-2022 走看看