先定义消息格式如下:
请求: #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-> ok end, {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 of undefined-> Defv; Els-> Val end .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 stub InputStreamReader 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 block System.out.println("recMsg error"+e.getMessage()); isrunning=false; } try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
测试结果如下:
启动一个客户端,修改其昵称为clientA
再启动一个客户端,修改昵称为clientB
clientB客户端获取当前在线用户(这里只打印昵称)