对方正在输入 java_smark和openfire即时通信代码

本文详细介绍了如何使用Java Smark库与Openfire服务器进行即时通信的实现,包括创建连接、发送消息、管理好友列表、监听好友状态、发送离线消息以及文件传输等功能。此外,还涉及到Openfire的配置和Smack库的相关知识点。
摘要由CSDN通过智能技术生成

出自:http://blog.csdn.net/casuallc/article/details/34794501

服务器:openfire

客户端程序:smark编写

首先安装openfire,下载客户端后直接安装即可,数据库可以用openfire自身的,也可以用自己的数据库,只要按提示设置好参数即可

之后,就可以用smark写一个客户端测试与openfire的通信了(需要引进的jar包除了smark自身的,还要引入xmlpull-1.1.3.1.jar、kxml2-2.3.0.jar两个包

,作用是解析xml文件)

备注:我用的smark版本是4.0,要引入的基本包有smack-core-4.0.0.jar、smack-debug-4.0.0.jar、smack-extensions-4.0.0.jar、smack-tcp-4.0.0.jar

debug包使用来调试的,tcp是用来初始化连接的、extension包里面含有发送离线消息、文件等类

下面是创建一个连接

[java] view plain copy

ConnectionConfiguration config = new ConnectionConfiguration("ip", 5222);

//设置成disabled,则不会去验证服务器证书是否有效,默认为enabled

config.setSecurityMode(SecurityMode.disabled);

//设置可以调试,默认为false,老版本的写法为XMPPConnection.DEBUG_ENABLED = true;

config.setDebuggerEnabled(true);

//设置是否在登陆的时候告诉服务器,默认为true

config.setSendPresence(false);

//XMPPConnection在后来的版本中改成了抽象类

XMPPConnection conn = new XMPPTCPConnection(config);

//设置等待时间

conn.setPacketReplyTimeout(5000);

conn.connect();

//用户名,密码,资源名(例如:如果是用潘迪安发送的消息,则资源名就是:  潘迪安,用于标识客户端)

conn.login("admin", "0", "资源名"); 关于连接的参数,在新版本中全部在config中设置

发送消息

[html] view plain copy

private void testSendMessage(XMPPConnection conn) throws Exception {

//jid在数据表中ofroster可以查到,一般是   用户名@服务器名称

Chat chat = ChatManager.getInstanceFor(conn).createChat("ly@192.168.1.100", new MessageListener() {

@Override

public void processMessage(Chat chat, Message message) {

System.out.println("Received message: " + message);

}

});

Message msg = new Message();

msg.setBody("hello world");

//定义成normal,在对象不在线时发送离线消息,消息存放在数据表ofoffline中

msg.setType(Message.Type.normal);

//发送消息,参数可以是字符串,也可以是message对象

chat.sendMessage(msg);

//发送广播

conn.sendPacket(msg);

}

发送离线消息

[java] view plain copy

private void testOffLine(XMPPConnection conn) throws Exception {

//离线文件

OfflineMessageManager offMM = new OfflineMessageManager(conn);

System.out.println("离线文件数量 :" + offMM.getMessageCount());

System.out.println("离线文件内容 :");

//经测试,当调用getMessages时,会触发chat设置的监听器,从而输出离线消息内容,但是getMessages方法返回的离线消息为空

//猜测回调函数的触发条件是一个变量,方变量改变时(while(flag)),执行回调函数

List listMessage = offMM.getMessages();

//listMessage的大小为0

System.out.println(listMessage.size());

for(Message m : offMM.getMessages()) {

System.out.println(" 离线  : " + m.getBody() + m.getBodies());

}

}

得到好友列表

[java] view plain copy

private void testGetRoster(XMPPConnection conn) throws Exception {

//得到该user的roster(相当于好友列表),不区分是否在线

Roster r = conn.getRoster();

Collection c = r.getEntries();

for(RosterEntry re : c) {

StringBuilder sb = new StringBuilder();

sb.append("name : ").append(re.getName());

sb.append("\nuser : ").append(re.getUser());

sb.append("\ntype : ").append(re.getType());

sb.append("\nstatus : ").append(re.getStatus());

System.out.println(sb.toString());

System.out.println("-----------------------------");

}

System.out.println(r.getEntries());

//输出内容

/*  name : null

user : ly@192.168.1.100

type : from

status : null

-----------------------------

name : null

user : yy@192.168.1.100

type : to

status : null

-----------------------------

[ly@192.168.1.100, yy@192.168.1.100]

*/

}

管理好友,监听好友请求

[java] view plain copy

 
 

[java] view plain copy

private void testAddAndDelFriends(final XMPPConnection conn) throws Exception {

Roster r = conn.getRoster();

// 用户的jid,昵称,用户的分组。如果该用户不存在也可以添加

//  r.createEntry("yy@192.168.1.100", "yy", null);

// rosterEntry的构造方法是包访问权限,不能直接new

//  RosterEntry entry = r.getEntry("ly@192.168.1.100");

// r.removeEntry(entry);

//监听所有的请求,之后可以过滤掉不想要的请求

PacketListener packetListener = new PacketListener() {

@Override

public void processPacket(Packet packet) throws NotConnectedException {

/*

available

unavailable

subscribe  发出添加好友的请求

subscribed 同意添加好友

unsubscribe 发出删除好友请求

unsubscribed 删除好友(即拒绝添加好友),

备注:对方发出添加好友的请求后,在服务器端会自动把对方加入到自己的roster,所以在执行处理好友请求或添加删除好友的时候,要重新获取roster,更新好友列表

*/

Presence presence = (Presence) packet;

Type type = presence.getType();

//请求添加好友

if(Type.subscribe.equals(type)) {

//注意点:要设置to(即指明要发送的对象,否则不能成功拒绝),至于from不用设置,因为在sendPacket方法中已经设置了,formMode初始化的时候为OMITTED,可以自己设置

/*

switch (fromMode) {

case OMITTED:

packet.setFrom(null);

break;

case USER:

packet.setFrom(getUser());//getUser是抽象方法

break;

*/

//直接用传来的presence,不能自己新建一个presence(可能要验证presence是否是原来的对象,来判断是谁拒绝了谁的好友请求),否则不能成功拒绝对方添加好友

//例:A--presence1-->B   A---presence2---C, C---presence3---A这样服务器就没办法判断是B、C中的哪一个拒绝了A的请求

presence.setType(Type.unsubscribed);//拒绝,发送了一条presence

//presence.setType(Type.unavailable);//发送了两条presence,一条是subscribed,一条是unavailabled,能接受对方消息,自己的状态显示隐身,再一次登录的时候显示在线

presence.setTo(presence.getFrom());

presence.setPacketID(presence.getPacketID());

Roster r = conn.getRoster();

try {

RosterEntry entry = r.getEntry(presence.getFrom());

if(entry != null)

r.removeEntry(entry);

} catch (NotLoggedInException | NoResponseException | XMPPErrorException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

conn.sendPacket(presence);

//多方删除自己

} else if(Type.unsubscribe.equals(type)) {

presence.setTo(presence.getFrom());

presence.setType(Type.unsubscribe);

Roster r = conn.getRoster();

try {

r.removeEntry(r.getEntry(presence.getFrom()));

} catch (NotLoggedInException | NoResponseException | XMPPErrorException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

conn.sendPacket(presence);

}

}

};

//      PacketFilter packetFilter = new PacketFilter() {

//

//          //如果返回false,则不把事件交给listener处理,否则会调用packetListener中的processPacket方法

//          //方法解释true if and only if packet passes the filter.

//          @Override

//          public boolean accept(Packet packet) {

//              System.out.println("2" + packet);

//              return true;

//          }

//      };

//过滤掉所有的不是好友请求、删除的所有packet

PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Presence.class));

conn.addPacketListener(packetListener, packetFilter);

//未知

RosterExchangeManager rem = new RosterExchangeManager(conn);

rem.addRosterListener(new RosterExchangeListener() {

@Override

public void entriesReceived(String from, Iterator remoteRosterEntries) {

System.out.println(from);

while(remoteRosterEntries.hasNext()) {

RemoteRosterEntry entry = remoteRosterEntries.next();

System.out.println(entry.getUser() + " : " + entry.getName());

}

}

});

}

得到好友的信息,主要是VCard类的使用

[java] view plain copy

private void testGetFriendInfo(XMPPConnection conn) throws Exception {

VCard vCard = new VCard();

VCardManager vcManager = new VCardManager();

//此处返回false

boolean b = vcManager.isSupported("ly@192.168.1.100", conn);

System.out.println(b);

vCard.load(conn, "ly@192.168.1.100");

// Load Avatar from VCard

byte[] avatarBytes = vCard.getAvatar();

//得不到头像等的信息

if(avatarBytes == null) {

return;

}

// To create an ImageIcon for Swing applications

ImageIcon icon = new ImageIcon(avatarBytes);

System.out.println(icon.getIconWidth() + " : " + icon.getIconHeight());

// To create just an image object from the bytes

ByteArrayInputStream bais = new ByteArrayInputStream(avatarBytes);

try {

Image image = ImageIO.read(bais);

FileOutputStream fos = new FileOutputStream("D://icon.jpg");

fos.write(avatarBytes);

fos.close();

}

catch (IOException e) {

e.printStackTrace();

}

}

设置自己的状态信息

[java] view plain copy

private void testSetInfo(XMPPConnection conn) throws Exception {

VCard vCard = new VCard();

vCard.load(conn);

vCard.setEmailHome("admin@126.com");

vCard.setAddressFieldWork("POSTAL", "汇宝大厦");

//修改完要保存修改的内容,否则没办法更新到服务器

vCard.save(conn);

//修改自身的状态,包括隐身,上线(可以指定对特定的好友更改状态)

Presence p = new Presence(Type.available);

p.setTo("ly@192.168.1.100");

//修改心情

p.setStatus("我的心情");

//同样要发到服务器

conn.sendPacket(p);

}

监听好友的状态

[java] view plain copy

private void testSetRosterListener(XMPPConnection conn) throws Exception {

Roster r = conn.getRoster();

r.createEntry("ly@192.168.1.100", "昵称", null);

r.addRosterListener(new RosterListener() {

@Override

public void presenceChanged(Presence presence) {

//更改状态信息时调用该方法(更改在线状态,修改心情,修改头像等)

System.out.println("presenceChanged");

}

@Override

public void entriesUpdated(Collection addresses) {

//该方法以及下面的方法都是在服务器修改好友信息时触发

System.out.println("entriesUpdated");

}

@Override

public void entriesDeleted(Collection addresses) {

// TODO Auto-generated method stub

System.out.println("entriesDeleted");

}

@Override

public void entriesAdded(Collection addresses) {

// TODO Auto-generated method stub

System.out.println("entriesAdded");

}

});

}

监听好友的输入状态

[java] view plain copy

private void testGetExtention(XMPPConnection conn) throws Exception {

Chat chat = ChatManager.getInstanceFor(conn).createChat("ly@192.168.1.100", new MessageListener() {

@Override

public void processMessage(Chat chat, Message message) {

//得到输入状态,分为五种:正在输入(composing),暂停输入(paused),发送(active),关闭对话框(gone)

PacketExtension pe = message.getExtension("http://jabber.org/protocol/chatstates");

switch (pe.getElementName()) {

case "composing":

System.out.println("正在输入......");

break;

case "paused":

System.out.println("正在冥想......");

break;

case "active":

System.out.println("对方已发送。");

break;

case "gone":

System.out.println("对话框已被关闭。");

break;

default:

break;

}

}

});

Message msg = new Message();

msg.addExtension(new ChatStateExtension(ChatState.gone));

msg.setBody("hello world");

chat.sendMessage(msg);

}

加入聊天室进行多人聊天

[java] view plain copy

private MultiUserChat multiUserChat;

private void testMutiUserChat(XMPPConnection conn) throws Exception {

MultiUserChat.addInvitationListener(conn, new InvitationListener() {

@Override

public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password, Message message) {

StringBuilder sb = new StringBuilder();

sb.append("房间号  : ").append(room);

sb.append("\n邀请者  : ").append(inviter);

sb.append("\n理由  : ").append(reason);

sb.append("\n密码  : ").append(password);

sb.append("\n消息  : ").append(message);

System.out.println(sb);

multiUserChat = new MultiUserChat(conn, room);

try {

multiUserChat.join("admin", password);

} catch (XMPPErrorException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SmackException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

multiUserChat.addMessageListener(new PacketListener() {

@Override

public void processPacket(Packet packet) throws NotConnectedException {

Message msg = (Message) packet;

System.out.println(msg.getBody());

}

});

}

});

while(true) {

try {

Thread.sleep(500);

if(multiUserChat == null)

continue;

//关于发送消息的问题,可以直接发字符串

//也可以发送message,但是要设定message的一些参数,否则不能发送(参数设置如下)

//用Chat发送消息时,不用设置,原因是在Chat的sendMessage方法中已经添加了这些参数

/*

*  message.setTo(participant);

message.setType(Message.Type.chat);

message.setThread(threadID);

*/

//但是,用MultiUserChat类中的sendMessage方法,直接调用了XMPPConnection中的sendPacket方法,没有设置Message的参数

Message msg = new Message();

//房间名称

msg.setTo("a@conference.192.168.1.100");

msg.setType(Message.Type.groupchat);

msg.setThread(Thread.currentThread().getId() + "");

msg.setBody("hello");

multiUserChat.sendMessage(msg);

break;

} catch (InterruptedException e) {

e.printStackTrace();

} catch (NotConnectedException e) {

e.printStackTrace();

} catch (XMPPException e) {

e.printStackTrace();

}

}

}

发送和接收文件

[java] view plain copy

private void testSendFile(XMPPConnection conn) throws Exception {

// 发送文件的管理器

FileTransferManager ftm = new FileTransferManager(conn);

ftm.addFileTransferListener(new FileTransferListener() {

@Override

public void fileTransferRequest(FileTransferRequest request) {

System.out.println(request.getFileName());

IncomingFileTransfer inComingFileTransfer = request.accept();

try {

//可以直接写到file文件中

File file = new File("D://" + request.getFileName());

inComingFileTransfer.recieveFile(file);

} catch (Exception e) {

e.printStackTrace();

}

}

});

// 注意jid格式,下面为标准格式,如果不对则会抛出jid格式错误的异常

// (if (parseName(jid).length() <= 0 || parseServer(jid).length() <= 0|| parseResource(jid).length() <= 0) {

// return false;

OutgoingFileTransfer oft = ftm.createOutgoingFileTransfer("admin@192.168.1.100/潘迪安");

File file = new File("D://time.jpg");

oft.sendFile(file, "图片");

System.out.println(oft.isDone());

} 创建多人聊天室

[java] view plain copy

private void testCreateRoom(XMPPConnection conn) throws Exception {

while(true) {

if(conn != null)

break;

}

//@之前的是会议房间名称,之后的是conference+ip(固定格式,不能改变)

MultiUserChat muc = new MultiUserChat(conn, "ly@conference.192.168.1.100");

//昵称,如果该房间已经存在,则会抛出Creation failed - Missing acknowledge of room creation.(先加入房间,然后离开房间)

muc.create("real_admin");

Form form = muc.getConfigurationForm();

Form submitForm = form.createAnswerForm();

//下面的初始化有什么用,在创建submitForm的时候已经设置参数了

//      List list = submitForm.getFields();

//      for(FormField f : list) {

//          if(!(FormField.TYPE_HIDDEN.equals(f.getType())) && f.getVariable() != null) {

//              submitForm.setDefaultAnswer(f.getVariable());

//          }

//      }

//参数到底是什么意思,为什么有的可以设置,有的不可以设置

/*

*  variable:FORM_TYPE  type:hidden  value:[http://jabber.org/protocol/muc#roomconfig]

variable:muc#roomconfig_roomname  type:text-single  value:[]

variable:muc#roomconfig_roomdesc  type:text-single  value:[]

variable:muc#roomconfig_changesubject  type:boolean  value:[]

variable:muc#roomconfig_maxusers  type:list-single  value:[]

variable:muc#roomconfig_presencebroadcast  type:list-multi  value:[]

variable:muc#roomconfig_publicroom  type:boolean  value:[]

variable:muc#roomconfig_persistentroom  type:boolean  value:[]

variable:muc#roomconfig_moderatedroom  type:boolean  value:[]

variable:muc#roomconfig_membersonly  type:boolean  value:[]

variable:muc#roomconfig_allowinvites  type:boolean  value:[]

variable:muc#roomconfig_passwordprotectedroom  type:boolean  value:[]

variable:muc#roomconfig_roomsecret  type:text-private  value:[]

variable:muc#roomconfig_whois  type:list-single  value:[]

variable:muc#roomconfig_enablelogging  type:boolean  value:[]

variable:x-muc#roomconfig_reservednick  type:boolean  value:[]

variable:x-muc#roomconfig_canchangenick  type:boolean  value:[]

variable:x-muc#roomconfig_registration  type:boolean  value:[]

variable:muc#roomconfig_roomadmins  type:jid-multi  value:[]

variable:muc#roomconfig_roomowners  type:jid-multi  value:[]

*/

//submitForm.setAnswer(FormField.TYPE_TEXT_PRIVATE, "0");

muc.sendConfigurationForm(submitForm);

//被拒绝时执行

muc.addInvitationRejectionListener(new InvitationRejectionListener() {

@Override

public void invitationDeclined(String invitee, String reason) {

System.out.println(invitee + " : " + reason);

}

});

muc.invite("yy@192.168.1.100", "ly_room");

}

管理房间

[java] view plain copy

private void testManageRoom(XMPPConnection conn) throws Exception {

testCreateRoom(conn);

MultiUserChat muc = new MultiUserChat(conn, "ly@conference.192.168.1.100");

//Thread.sleep(5000);

//赋予管理员权限

//muc.grantAdmin("yy@192.168.1.100");

//Thread.sleep(5000);

//如果是管理员,则不能踢除

//muc.banUser("yy@192.168.1.100", "太水");

//收回说话的权限

muc.revokeVoice("yy");

//muc.grantVoice("yy");

}

注册

[java] view plain copy

private void testRegister(XMPPConnection conn) throws Exception {

//可以直接改登陆用户的信息(如果是username的值必须和该用户的用户名相同)

Registration r = new Registration();

Map attributes = new HashMap();

attributes.put("username", "newuser");

attributes.put("password", "0");

attributes.put("email", "new00@126.com");

attributes.put("name", "name@192.168.1.100");

//添加用户,要设置type类型为set,原因不明

r.setType(IQ.Type.SET);

r.setAttributes(attributes);

//过滤器,用来过滤由服务器返回的信息(即得到注册信息的内容)

PacketFilter packetFilter = new AndFilter(new PacketIDFilter(r.getPacketID()), new PacketTypeFilter(IQ.class));

PacketCollector collector = conn.createPacketCollector(packetFilter);

System.out.println(r);

conn.sendPacket(r);

IQ result = (IQ) collector.nextResult();

if(result == null) {

System.out.println("服务器没有返回任何信息");

} else {

switch (result.getType().toString()) {

case "result":

System.out.println("注册成功");

break;

case "error":

if(result.getError().toString().equalsIgnoreCase("conflict"))

System.out.println("用户名称已存在");

else

System.out.println("注册失败");

break;

default:

break;

}

}

}

管理账号密码

[java] view plain copy

private void testModifyPwd(XMPPConnection conn) throws Exception {

//创建一个用户信息管理,可以创建新用户,或者修改用户密码

AccountManager am = AccountManager.getInstance(conn);

Collection c = am.getAccountAttributes();

for(String s : c) {

System.out.println(s);

}

/*

* 通过accountManager可以得到的属性

*  username

email

registered

name

password

*/

am.getAccountAttribute("username");

am.createAccount("newUser", "0");

am.changePassword("00");

}

至于细节和中间遇到的问题,在程序代码中都有叙述

参考博客: http://blog.csdn.net/shimiso/article/details/11225873

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值