热门标签 | 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客户端获取当前在线用户(这里只打印昵称)




推荐阅读
  • Java Socket 关键参数详解与优化建议
    Java Socket 的 API 虽然被广泛使用,但其关键参数的用途却鲜为人知。本文详细解析了 Java Socket 中的重要参数,如 backlog 参数,它用于控制服务器等待连接请求的队列长度。此外,还探讨了其他参数如 SO_TIMEOUT、SO_REUSEADDR 等的配置方法及其对性能的影响,并提供了优化建议,帮助开发者提升网络通信的稳定性和效率。 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
  • Python 程序转换为 EXE 文件:详细解析 .py 脚本打包成独立可执行文件的方法与技巧
    在开发了几个简单的爬虫 Python 程序后,我决定将其封装成独立的可执行文件以便于分发和使用。为了实现这一目标,首先需要解决的是如何将 Python 脚本转换为 EXE 文件。在这个过程中,我选择了 Qt 作为 GUI 框架,因为之前对此并不熟悉,希望通过这个项目进一步学习和掌握 Qt 的基本用法。本文将详细介绍从 .py 脚本到 EXE 文件的整个过程,包括所需工具、具体步骤以及常见问题的解决方案。 ... [详细]
  • 使用Maven JAR插件将单个或多个文件及其依赖项合并为一个可引用的JAR包
    本文介绍了如何利用Maven中的maven-assembly-plugin插件将单个或多个Java文件及其依赖项打包成一个可引用的JAR文件。首先,需要创建一个新的Maven项目,并将待打包的Java文件复制到该项目中。通过配置maven-assembly-plugin,可以实现将所有文件及其依赖项合并为一个独立的JAR包,方便在其他项目中引用和使用。此外,该方法还支持自定义装配描述符,以满足不同场景下的需求。 ... [详细]
  • 本文详细介绍了一种利用 ESP8266 01S 模块构建 Web 服务器的成功实践方案。通过具体的代码示例和详细的步骤说明,帮助读者快速掌握该模块的使用方法。在疫情期间,作者重新审视并研究了这一未被充分利用的模块,最终成功实现了 Web 服务器的功能。本文不仅提供了完整的代码实现,还涵盖了调试过程中遇到的常见问题及其解决方法,为初学者提供了宝贵的参考。 ... [详细]
  • 本文详细介绍了 InfluxDB、collectd 和 Grafana 的安装与配置流程。首先,按照启动顺序依次安装并配置 InfluxDB、collectd 和 Grafana。InfluxDB 作为时序数据库,用于存储时间序列数据;collectd 负责数据的采集与传输;Grafana 则用于数据的可视化展示。文中提供了 collectd 的官方文档链接,便于用户参考和进一步了解其配置选项。通过本指南,读者可以轻松搭建一个高效的数据监控系统。 ... [详细]
  • MySQL Decimal 类型的最大值解析及其在数据处理中的应用艺术
    在关系型数据库中,表的设计与SQL语句的编写对性能的影响至关重要,甚至可占到90%以上。本文将重点探讨MySQL中Decimal类型的最大值及其在数据处理中的应用技巧,通过实例分析和优化建议,帮助读者深入理解并掌握这一重要知识点。 ... [详细]
  • 本文详细解析了客户端与服务器之间的交互过程,重点介绍了Socket通信机制。IP地址由32位的4个8位二进制数组成,分为网络地址和主机地址两部分。通过使用 `ipconfig /all` 命令,用户可以查看详细的IP配置信息。此外,文章还介绍了如何使用 `ping` 命令测试网络连通性,例如 `ping 127.0.0.1` 可以检测本机网络是否正常。这些技术细节对于理解网络通信的基本原理具有重要意义。 ... [详细]
  • DVWA学习笔记系列:深入理解CSRF攻击机制
    DVWA学习笔记系列:深入理解CSRF攻击机制 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 在List和Set集合中存储Object类型的数据元素 ... [详细]
  • 本指南介绍了如何在ASP.NET Web应用程序中利用C#和JavaScript实现基于指纹识别的登录系统。通过集成指纹识别技术,用户无需输入传统的登录ID即可完成身份验证,从而提升用户体验和安全性。我们将详细探讨如何配置和部署这一功能,确保系统的稳定性和可靠性。 ... [详细]
  • 本文探讨了如何利用Java代码获取当前本地操作系统中正在运行的进程列表及其详细信息。通过引入必要的包和类,开发者可以轻松地实现这一功能,为系统监控和管理提供有力支持。示例代码展示了具体实现方法,适用于需要了解系统进程状态的开发人员。 ... [详细]
author-avatar
key920721
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有