从:http://blog.csdn.net/casuallc/article/details/34794501
server:openfire
client计划:smark写
首先安装openfire,下载client直接安装就可以。数据库能够用openfire自身的,也能够用自己的数据库,仅仅要按提示设置好參数就可以
之后,就能够用smark写一个client測试与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包里面含有发送离线消息、文件等类
以下是创建一个连接
- ConnectionConfiguration config = new ConnectionConfiguration("ip", 5222);
- //设置成disabled。则不会去验证server证书是否有效,默觉得enabled
- config.setSecurityMode(SecurityMode.disabled);
- //设置能够调试。默觉得false,老版本号的写法为XMPPConnection.DEBUG_ENABLED = true;
- config.setDebuggerEnabled(true);
- //设置是否在登陆的时候告诉server,默觉得true
- config.setSendPresence(false);
- //XMPPConnection在后来的版本号中改成了抽象类
- XMPPConnection conn = new XMPPTCPConnection(config);
- //设置等待时间
- conn.setPacketReplyTimeout(5000);
- conn.connect();
- //username,password,资源名(比如:假设是用潘迪安发送的消息。则资源名就是: 潘迪安,用于标识client)
- conn.login("admin", "0", "资源名");
发送消息
- private void testSendMessage(XMPPConnection conn) throws Exception {
- //jid在数据表中ofroster能够查到。通常是 username@server名称
- 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);
- }
发送离线消息
- 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<Message> listMessage = offMM.getMessages();
- //listMessage的大小为0
- System.out.println(listMessage.size());
- for(Message m : offMM.getMessages()) {
- System.out.println(" 离线 : " + m.getBody() + m.getBodies());
- }
- }
得到好友列表
- private void testGetRoster(XMPPConnection conn) throws Exception {
- //得到该user的roster(相当于好友列表),不区分是否在线
- Roster r = conn.getRoster();
- Collection<RosterEntry> c = r.getEntries();
- for(RosterEntry re : c) {
- StringBuilder sb = new StringBuilder();
- sb.append("name : ").append(re.getName());
- sb.append(" user : ").append(re.getUser());
- sb.append(" type : ").append(re.getType());
- sb.append(" status : ").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]
- */
- }
管理好友,监听好友请求
- <pre name="code" class="java">
- </pre><pre name="code" class="java">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 删除好友(即拒绝加入好友)。
- 备注:对方发出加入好友的请求后。在server端会自己主动把对方加入到自己的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这样server就没办法推断是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<RemoteRosterEntry> remoteRosterEntries) {
- System.out.println(from);
- while(remoteRosterEntries.hasNext()) {
- RemoteRosterEntry entry = remoteRosterEntries.next();
- System.out.println(entry.getUser() + " : " + entry.getName());
- }
- }
- });
- }
得到好友的信息。主要是VCard类的使用
- 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();
- }
- }
设置自己的状态信息
- private void testSetInfo(XMPPConnection conn) throws Exception {
- VCard vCard = new VCard();
- vCard.load(conn);
- vCard.setEmailHome("admin@126.com");
- vCard.setAddressFieldWork("POSTAL", "汇宝大厦");
- //改动完要保存改动的内容,否则没办法更新到server
- vCard.save(conn);
- //改动自身的状态,包含隐身,上线(能够指定对特定的好友更改状态)
- Presence p = new Presence(Type.available);
- p.setTo("ly@192.168.1.100");
- //改动心情
- p.setStatus("我的心情");
- //相同要发到server
- conn.sendPacket(p);
- }
监听好友的状态
- 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<String> addresses) {
- //该方法以及以下的方法都是在server改动好友信息时触发
- System.out.println("entriesUpdated");
- }
- @Override
- public void entriesDeleted(Collection<String> addresses) {
- // TODO Auto-generated method stub
- System.out.println("entriesDeleted");
- }
- @Override
- public void entriesAdded(Collection<String> addresses) {
- // TODO Auto-generated method stub
- System.out.println("entriesAdded");
- }
- });
- }
监听好友的输入状态
- 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);
- }
增加聊天室进行多人聊天
- 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(" 邀请者 : ").append(inviter);
- sb.append(" 理由 : ").append(reason);
- sb.append(" 密码 : ").append(password);
- sb.append(" 消息 : ").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();
- }
- }
- }
发送和接收文件
- 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());
- }
- 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<FormField> 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");
- }
管理房间
- <pre name="code" class="java">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");
- }
注冊
- private void testRegister(XMPPConnection conn) throws Exception {
- //能够直接改登陆用户的信息(假设是username的值必须和该用户的用户名同样)
- Registration r = new Registration();
- Map<String, String> attributes = new HashMap<String, String>();
- 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);
- //过滤器,用来过滤由server返回的信息(即得到注冊信息的内容)
- 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("server没有返回不论什么信息");
- } 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;
- }
- }
- }
管理账号password
- private void testModifyPwd(XMPPConnection conn) throws Exception {
- //创建一个用户信息管理,能够创建新用户。或者改动用户密码
- AccountManager am = AccountManager.getInstance(conn);
- Collection<String> c = am.getAccountAttributes();
- for(String s : c) {
- System.out.println(s);
- }
- /*
- * 通过accountManager能够得到的属性
- * username
- registered
- name
- password
- */
- am.getAccountAttribute("username");
- am.createAccount("newUser", "0");
- am.changePassword("00");
- }
至于细节,中遇到,我在程序代码描述
参考博客:
http://blog.csdn.net/shimiso/article/details/11225873