热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Erlang聊天室程序(七)获取在线用户

先定义消息格式如下:请求:#message{type"get",subject"clienti

              先定义消息格式如下:

              请求: #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客户端获取当前在线用户(这里只打印昵称)




推荐阅读
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • Imtryingtofigureoutawaytogeneratetorrentfilesfromabucket,usingtheAWSSDKforGo.我正 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
author-avatar
缺氧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有