Erlang 聊天室程序(七) 获取在线用户
来源:互联网 发布:大金空调挂机推荐 知乎 编辑:程序博客网 时间:2024/04/30 13:25
先定义消息格式如下:
请求: #message{type="get",subject="clientinfo",content="all"}
响应:#message{type="result",subject="clientinfo",content=[#clientinfo,#clientinfo,.....]}
修改客户端发送请求消息部分:
clientThread.sendMsg(new Message("get","client","","clientinfo","all"));
修改服务器端,给chat_room添加一个获取所有在线用户的方法:
getMembers(Message)->gen_server:call(?MODULE, {get_member,Message}).
在路由模块根据message.type 和message.subject将请求信息路由到以上方法
routeMessage(Type,Sub,Message)->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"->chat_room:setUserInfo(Message);_Els->io:format("unkonw msssage subject:~p~n",[Sub])end;"get"->case Sub of"clientinfo"->chat_room:getMembers(Message); _Els->io:format("unkonw msssage subject:~p~n",[Sub]) end;_Els->{error,"wrong message type"} end.chat_room中处理get_member的调用,在里面定义一个本地方法getClient使用client_manager以#clientinfo格式获取在线用户
chat_room.erl:
handle_call({get_member,Msg},From,State)->#message{content=Content}=Msg,case binary_to_list(Content) of"all"->List=getClient([],[]),#message{from=Id}=Msg,TheFrom=client_manager:getNick(Id),Message=Msg#message{type="result",from=TheFrom,subject="clientinfo",content=List},{Pid,_}=From,Pid!{get_member,Message}; _Els->okend,{reply,ok,State};getClient(Key,UList)-> case client_manager:getNextClient(Key) of [Record]-> Next=Record#clientinfo.id, io:format("record is:~p~n",[Record]), Json=util_SetInfoParas:deparaElement(Record), io:format("clientSession found:~p~n",[Record]), NewUList=[Json|UList], getClient([Next],NewUList); []-> UList end.
这里为了方便后面的解析,返回的客户信息需要预先编码为JSONString在Erlang下decode后的格式,所以根据需要在util_setInfoParas.erl中定义了deparaElement/1方法
deparaElement(Record)->#clientinfo{nick=Nick,sex=Sex,age=Age,province=Province,city=City,posx=Px,posy=Py}=Record,{obj,[ {"nick",list_to_binary(setDef(Nick,"s"))}, {"sex",setDef(Sex,"i")}, {"age",setDef(Age,"i")}, {"province",list_to_binary(setDef(Province,"s"))}, {"city",list_to_binary(setDef(City,"s"))}, {"posx",setDef(Px,"i")}, {"posy",setDef(Py,"i")} ]}.setDef(Val,Type)->Defv=case Type of "s"->""; "i"->0; "l"->[]end,case Val ofundefined->Defv;Els->Valend.chat_room处理后会将结果打包成一个Message发送给对应的客户端进程,客户端进程再发送给最终的客户端
handle_info({get_member,Message},State)->io:format("client_session-getmember result ~p~n",[Message]),sendMsg(Message,State),{noreply,State};
再修改客户端JAVA代码,将收到的JSONString转换为Bean对象。这里专门新建一个类GetUserInfo表示接收到的result信息
package com.kinglong.socket.data;import java.util.ArrayList;import java.util.Date;import net.sf.json.JSONArray;import net.sf.json.JSONObject;public class GetUserInfo extends Packet{ArrayList<ClientInfo> content=null;public GetUserInfo(){this.json=new JSONObject();setType("get");setSubject("clientinfo");setCreationDate(new Date());}public GetUserInfo(ArrayList<ClientInfo>list){this.json=new JSONObject();setType("get");setSubject("clientinfo");setCreationDate(new Date());setContent(list);}public ArrayList<ClientInfo> getContent() {JSONArray array=json.getJSONArray("content");ArrayList<ClientInfo> infos = new ArrayList<ClientInfo>();int size=array.size();for(int i=0;i<size;i++){JSONObject obj=array.getJSONObject(i);infos.add((ClientInfo)JSONObject.toBean(obj, ClientInfo.class));}if(array==null){return null;}else{if(content!=null){return content;}else{content=infos;return content;}}}public void setContent(ArrayList<ClientInfo> clients) {if(clients!=null){this.content = clients;}this.json.put("content", clients);}}再修改客户端接收部分的代码,将对应类型的消息解析
public void run() {// TODO Auto-generated method stubInputStreamReader reader = new InputStreamReader(inst);BufferedReader bfreader = new BufferedReader(reader);while(isrunning){String str=null;try {byte[] data =new byte[1024];int len =0;while((len=inst.read(data))>0){str=new String(data).trim();Iterator<JSONObject> it =JSONParaser.getString(str);while(it.hasNext()){JSONObject obj=it.next();if("msg".equals(obj.get("type"))){Message msg =(Message)JSONObject.toBean(obj,Message.class);mf.recMsg(msg);}else if("result".equals(obj.get("type"))&&"clientinfo".equals(obj.get("subject"))){Map<String,Class>mapclass = new HashMap<String,Class>();mapclass.put("content", ClientInfo.class);GetUserInfo info=(GetUserInfo)JSONObject.toBean(obj,GetUserInfo.class,mapclass);Iterator<ClientInfo> clients=info.getContent().iterator();while(clients.hasNext()){ClientInfo in =clients.next();mf.recMsg("there are client nick:"+in.getNick());}}}}} catch (IOException e) {// TODO Auto-generated catch blockSystem.out.println("recMsg error"+e.getMessage());isrunning=false;}try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
测试结果如下:
启动一个客户端,修改其昵称为clientA
再启动一个客户端,修改昵称为clientB
clientB客户端获取当前在线用户(这里只打印昵称)
- Erlang 聊天室程序(七) 获取在线用户
- Erlang 聊天室程序( 一)
- Erlang 聊天室程序( 一)
- Erlang 聊天室程序
- 在线聊天室小程序
- Erlang 聊天室程序(二) 客户端的退出
- Erlang 聊天室程序(五) 设置客户端信息
- erlang 聊天室
- 获取在线用户
- 获取用户在线列表
- 微信小程序之七(聊天室)
- Erlang 聊天室程序(三) 数据交换格式---json的decode
- Erlang 聊天室程序(四) 数据交换格式---json的encode
- Erlang 聊天室程序(六) 设置客户端信息2
- Erlang 聊天室程序(八) 主题房间---supervisor 的使用
- 第五天 CSDN (复习、聊天室、实现在线用户列表)
- Erlang TCP编程:聊天室
- red5获取在线用户列表
- C语言实现 vector( 动态数组) 改进版
- Ogre 1.8 Static Geomety /Instanced Geometry
- cout输出十进制、八进制、十六进制
- Symbolic link
- 带指针的【七彩时钟】(C语言)
- Erlang 聊天室程序(七) 获取在线用户
- freemaker
- Ubuntu下android NDK开发,实例演示
- Linux 安装oracle内核参数
- OverSIm: A cRuntimeError exception
- xuzhimo
- Velocity
- Linux开发环境熟悉-svn
- VC中的ComBox控件详解 .