先定义消息格式如下:
请求: #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 cOntent=null;
public GetUserInfo(){
this.json=new JSONObject();
setType("get");
setSubject("clientinfo");
setCreationDate(new Date());
}
public GetUserInfo(ArrayListlist){
this.json=new JSONObject();
setType("get");
setSubject("clientinfo");
setCreationDate(new Date());
setContent(list);
}
public ArrayList getContent() {
JSONArray array=json.getJSONArray("content");
ArrayList infos = new ArrayList();
int size=array.size();
for(int i=0;iJSONObject 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 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 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"))){
Mapmapclass = new HashMap();
mapclass.put("content", ClientInfo.class);
GetUserInfo info=(GetUserInfo)JSONObject.toBean(obj,GetUserInfo.class,mapclass);
Iterator 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客户端获取当前在线用户(这里只打印昵称)