1. package com.testV3;
  2. import java.util.List;
  3. import org.jivesoftware.smack.ConnectionListener;
  4. import org.jivesoftware.smack.SmackException.NoResponseException;
  5. import org.jivesoftware.smack.SmackException.NotConnectedException;
  6. import org.jivesoftware.smack.XMPPConnection;
  7. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  8. import org.jivesoftware.smack.packet.Presence;
  9. import org.jivesoftware.smack.tcp.XMPPTCPConnection;
  10. import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
  11. import org.jivesoftware.smackx.pubsub.ItemPublishEvent;
  12. import org.jivesoftware.smackx.pubsub.LeafNode;
  13. import org.jivesoftware.smackx.pubsub.PayloadItem;
  14. import org.jivesoftware.smackx.pubsub.PubSubManager;
  15. import org.jivesoftware.smackx.pubsub.SubscribeForm;
  16. import org.jivesoftware.smackx.pubsub.Subscription;
  17. import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
  18. import org.jivesoftware.smackx.xdata.packet.DataForm;
  19. import org.jxmpp.jid.parts.Resourcepart;
  20. public class SubscribeThread extends Thread {
  21. private String[] nodeId;
  22. private String userName;
  23. private String password;
  24. private String xmppDomain;
  25. private String serverName;
  26. private XMPPTCPConnection connection;
  27. private ItemEventListener<PayloadItem> myInterface;
  28. /**
  29. *
  30. * @param userName
  31. * @param password
  32. * @param xmppDomain
  33. * @param serverName
  34. * @param nodeId
  35. * 监听节点集合
  36. */
  37. public SubscribeThread(String userName, String password, String xmppDomain, String serverName, String[] nodeId) {
  38. this.userName = userName;
  39. this.password = password;
  40. this.xmppDomain = xmppDomain;
  41. this.serverName = serverName;
  42. this.nodeId = nodeId;
  43. try {
  44. if (connection == null) {
  45. getConnection(userName, password, xmppDomain, serverName);
  46. }
  47. } catch (Exception e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. /**
  52. *
  53. * @param userName
  54. * @param password
  55. * @param xmppDomain
  56. * @param serverName
  57. * @param nodeId
  58. * 监听节点集合
  59. * @param myInterface
  60. * 监听数据处理接口
  61. */
  62. public SubscribeThread(String userName, String password, String xmppDomain, String serverName, String[] nodeId,
  63. ItemEventListener myInterface) {
  64. this.userName = userName;
  65. this.password = password;
  66. this.xmppDomain = xmppDomain;
  67. this.serverName = serverName;
  68. this.nodeId = nodeId;
  69. this.myInterface = myInterface;
  70. try {
  71. if (connection == null) {
  72. getConnection(userName, password, xmppDomain, serverName);
  73. }
  74. } catch (Exception e) {
  75. e.printStackTrace();
  76. }
  77. }
  78. /**
  79. * 获取连接
  80. *
  81. * @param userName
  82. * @param password
  83. * @param xmppDomain
  84. * @param serverName
  85. */
  86. public void getConnection(String userName, String password, String xmppDomain, String serverName) {
  87. try {
  88. XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
  89. configBuilder.setUsernameAndPassword(userName, password);
  90. configBuilder.setXmppDomain(xmppDomain);
  91. /*Resourcepart resource = Resourcepart.from("pc");
  92. configBuilder.setResource(resource);*/
  93. configBuilder.setSendPresence(true);
  94. //configBuilder.setSendPresence(false);// 状态设为离线,目的为了取离线消息
  95. configBuilder.setDebuggerEnabled(true);//设置Debugger模式
  96. configBuilder.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.disabled);
  97. connection = new XMPPTCPConnection(configBuilder.build());
  98. connection.addConnectionListener(new MyConnectionListener(connection, nodeId, myInterface));
  99. // 连接服务器
  100. connection.connect();
  101. // 登录服务器
  102. connection.login();
  103. /*Presence presence = new Presence(Presence.Type.available);
  104. connection.sendPacket(presence); */
  105. } catch (Exception e) {
  106. e.printStackTrace();
  107. }
  108. }
  109. public void run() {
  110. while (true) {
  111. }
  112. }
  113. }
  1. package com.testV3;
  2. import java.io.IOException;
  3. import java.util.List;
  4. import java.util.Timer;
  5. import java.util.TimerTask;
  6. import org.jivesoftware.smack.AbstractXMPPConnection;
  7. import org.jivesoftware.smack.ConnectionListener;
  8. import org.jivesoftware.smack.SmackException;
  9. import org.jivesoftware.smack.SmackException.NotConnectedException;
  10. import org.jivesoftware.smack.StanzaListener;
  11. import org.jivesoftware.smack.XMPPConnection;
  12. import org.jivesoftware.smack.XMPPException;
  13. import org.jivesoftware.smack.filter.StanzaFilter;
  14. import org.jivesoftware.smack.packet.Message;
  15. import org.jivesoftware.smack.packet.Presence;
  16. import org.jivesoftware.smack.packet.Stanza;
  17. import org.jivesoftware.smack.packet.StreamError;
  18. import org.jivesoftware.smack.packet.XMPPError;
  19. import org.jivesoftware.smack.tcp.XMPPTCPConnection;
  20. import org.jivesoftware.smackx.ping.PingFailedListener;
  21. import org.jivesoftware.smackx.pubsub.ConfigurationEvent;
  22. import org.jivesoftware.smackx.pubsub.ItemPublishEvent;
  23. import org.jivesoftware.smackx.pubsub.LeafNode;
  24. import org.jivesoftware.smackx.pubsub.PayloadItem;
  25. import org.jivesoftware.smackx.pubsub.PubSubManager;
  26. import org.jivesoftware.smackx.pubsub.SubscribeForm;
  27. import org.jivesoftware.smackx.pubsub.Subscription;
  28. import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
  29. import org.jivesoftware.smackx.pubsub.listener.NodeConfigListener;
  30. import org.jivesoftware.smackx.xdata.packet.DataForm;
  31. import org.jxmpp.jid.parts.Resourcepart;
  32. public class MyConnectionListener implements ConnectionListener, PingFailedListener {
  33. private String[] nodeId;
  34. private XMPPTCPConnection connection;
  35. private ItemEventListener myInterface;
  36. private boolean subscribed = false; // 是否已注册监听订阅事件
  37. private Timer tPing;
  38. private Timer tReconn;
  39. private int logintime = 30 * 1000;
  40. class ReconnTimetask extends TimerTask {
  41. @Override
  42. public void run() {
  43. if (!connection.isConnected() || !connection.isAuthenticated()) {
  44. System.out.println("断开重连...");
  45. connection.disconnect();
  46. // 连接服务器
  47. try {
  48. connection.connect();
  49. // 登录服务器
  50. connection.login();
  51. Presence presence = new Presence(Presence.Type.available);
  52. connection.sendPacket(presence);
  53. } catch (Exception e) {
  54. // TODO Auto-generated catch block
  55. e.printStackTrace();
  56. }
  57. }
  58. }
  59. }
  60. class PingTimetask extends TimerTask {
  61. @Override
  62. public void run() {
  63. if (connection.isConnected() && connection.isAuthenticated()) {
  64. Presence presence = new Presence(Presence.Type.available);
  65. try {
  66. connection.sendPacket(presence);
  67. } catch (Exception e) {
  68. // TODO Auto-generated catch block
  69. e.printStackTrace();
  70. }
  71. }
  72. }
  73. }
  74. public MyConnectionListener(XMPPTCPConnection connection, String[] nodeId) {
  75. this.connection = connection;
  76. this.nodeId = nodeId;
  77. }
  78. public MyConnectionListener(XMPPTCPConnection connection, String[] nodeId, ItemEventListener myInterface) {
  79. this.connection = connection;
  80. this.nodeId = nodeId;
  81. this.myInterface = myInterface;
  82. }
  83. public void connected(XMPPConnection connection) {
  84. // TODO Auto-generated method stub
  85. System.out.println("connection");
  86. }
  87. public void authenticated(final XMPPConnection connection, boolean resumed) {
  88. // TODO Auto-generated method stub
  89. System.out.println("authenticated");
  90. try {
  91. if (!subscribed) {
  92. subscribed = true;
  93. // ping定时器3分钟
  94. //tPing = new Timer();
  95. //tPing.schedule(new PingTimetask(), logintime, 3 * 60 * 1000);
  96. // 添加订阅监听
  97. if (myInterface == null) {
  98. subscribeListener(nodeId, new MyItemEventListener());
  99. } else {
  100. subscribeListener(nodeId, myInterface);
  101. }
  102. MyPingManager.setDefaultPingInterval(30);// Ping every 10 seconds
  103. MyPingManager myPingManager = MyPingManager.getInstanceFor(connection);
  104. // Set PingListener here to catch connect status
  105. myPingManager.registerPingFailedListener(MyConnectionListener.this);
  106. // 添加接受数据监听
  107. connection.addAsyncStanzaListener(new StanzaListener() {
  108. public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
  109. // TODO Auto-generated method stub
  110. System.out.println("截获的内容:" + packet.toXML());
  111. if (packet instanceof Presence) {
  112. Presence presence = (Presence) packet;
  113. System.out.println("在线状态:" + presence.getType());
  114. if (presence.getType().equals(Presence.Type.unavailable)) {// 证明已掉线
  115. tReconn = new Timer();
  116. tReconn.schedule(new ReconnTimetask(), logintime);
  117. }
  118. }
  119. }
  120. }, new StanzaFilter() {
  121. public boolean accept(Stanza stanza) {
  122. // TODO Auto-generated method stub
  123. return true;
  124. }
  125. });
  126. }
  127. } catch (Exception e) {
  128. // TODO Auto-generated catch block
  129. e.printStackTrace();
  130. }
  131. }
  132. public void connectionClosed() {
  133. // TODO Auto-generated method stub
  134. System.out.println("connectionClosed");
  135. try {
  136. tReconn = new Timer();
  137. tReconn.schedule(new ReconnTimetask(), logintime);
  138. } catch (Exception e) {
  139. e.printStackTrace();
  140. }
  141. }
  142. public void connectionClosedOnError(Exception e) {
  143. // TODO Auto-generated method stub
  144. System.out.println("connectionClosedOnError");
  145. try {
  146. tReconn = new Timer();
  147. tReconn.schedule(new ReconnTimetask(), logintime);
  148. } catch (Exception ee) {
  149. e.printStackTrace();
  150. ee.printStackTrace();
  151. }
  152. }
  153. public void reconnectionSuccessful() {
  154. // TODO Auto-generated method stub
  155. System.out.println("reconnectionSuccessful");
  156. }
  157. public void reconnectingIn(int seconds) {
  158. // TODO Auto-generated method stub
  159. System.out.println("reconnectingIn");
  160. }
  161. public void reconnectionFailed(Exception e) {
  162. // TODO Auto-generated method stub
  163. System.out.println("reconnectionFailed");
  164. }
  165. /**
  166. * 订阅节点监听及数据处理
  167. *
  168. * @param nodeId
  169. * @param myItemEventListener
  170. * @throws Exception
  171. */
  172. public void subscribeListener(String[] nodeId, ItemEventListener<PayloadItem> myItemEventListener)
  173. throws Exception {
  174. PubSubManager mgr = PubSubManager.getInstance(connection);
  175. if (nodeId != null && nodeId.length > 0) {
  176. for (String id : nodeId) {
  177. // Get the node
  178. LeafNode node = null;
  179. node = mgr.getNode(id);
  180. SubscribeForm subscriptionForm = new SubscribeForm(DataForm.Type.submit);
  181. subscriptionForm.setDeliverOn(true);
  182. subscriptionForm.setDigestFrequency(5000);
  183. subscriptionForm.setDigestOn(true);
  184. subscriptionForm.setIncludeBody(true);
  185. if (myItemEventListener != null) {
  186. node.removeItemEventListener(myItemEventListener);
  187. node.addItemEventListener(myItemEventListener);
  188. } else {
  189. myItemEventListener = new ItemEventListener<PayloadItem>() {
  190. public void handlePublishedItems(ItemPublishEvent<PayloadItem> items) {
  191. List<PayloadItem> list = (List<PayloadItem>) items.getItems();
  192. for (PayloadItem item : list) {
  193. System.out.println("订阅消息内容:" + item.getPayload().toXML());
  194. }
  195. }
  196. };
  197. node.removeItemEventListener(myItemEventListener);
  198. node.addItemEventListener(myItemEventListener);
  199. }
  200. List<Subscription> subscriptions = node.getSubscriptions();
  201. boolean flag = true;
  202. if (subscriptions != null && subscriptions.size() > 0) {
  203. for (Subscription s : subscriptions) {
  204. if (s.getJid().toLowerCase()
  205. .equals(connection.getUser().asEntityBareJidString().toLowerCase())) {// 已订阅过
  206. flag = false;
  207. break;
  208. }
  209. }
  210. }
  211. if (flag) {// 未订阅,开始订阅
  212. node.subscribe(connection.getUser().asEntityBareJidString(), subscriptionForm);
  213. }
  214. }
  215. }
  216. }
  217. public void pingFailed() {
  218. // TODO Auto-generated method stub
  219. if (connection.isConnected()) {
  220. connection.disconnect();
  221. }
  222. tReconn = new Timer();
  223. tReconn.schedule(new ReconnTimetask(), logintime);
  224. }
  225. }
  1. package com.testV3;
  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. import java.util.List;
  5. import org.jivesoftware.smackx.pubsub.ItemPublishEvent;
  6. import org.jivesoftware.smackx.pubsub.PayloadItem;
  7. import org.jivesoftware.smackx.pubsub.listener.ItemEventListener;
  8. class MyItemEventListener implements ItemEventListener<PayloadItem> {
  9. public void handlePublishedItems(ItemPublishEvent<PayloadItem> items) {
  10. List<PayloadItem> list = (List<PayloadItem>) items.getItems();
  11. for (PayloadItem item : list) {
  12. Date d = new Date();
  13. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  14. //System.out.println("当前时间:" + sdf.format(d));
  15. System.out.println(sdf.format(d)+",订阅消息内容:" + item.getPayload().toXML());
  16. }
  17. }
  18. }
  1. package com.testV3;
  2. /**
  3. *
  4. * Copyright 2012-2015 Florian Schmaus
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. import java.util.Collections;
  19. import java.util.HashSet;
  20. import java.util.Map;
  21. import java.util.Set;
  22. import java.util.WeakHashMap;
  23. import java.util.concurrent.Executors;
  24. import java.util.concurrent.ScheduledExecutorService;
  25. import java.util.concurrent.ScheduledFuture;
  26. import java.util.concurrent.TimeUnit;
  27. import java.util.logging.Level;
  28. import java.util.logging.Logger;
  29. import org.jivesoftware.smack.AbstractConnectionClosedListener;
  30. import org.jivesoftware.smack.SmackException;
  31. import org.jivesoftware.smack.SmackException.NoResponseException;
  32. import org.jivesoftware.smack.SmackException.NotConnectedException;
  33. import org.jivesoftware.smack.XMPPConnection;
  34. import org.jivesoftware.smack.ConnectionCreationListener;
  35. import org.jivesoftware.smack.Manager;
  36. import org.jivesoftware.smack.XMPPConnectionRegistry;
  37. import org.jivesoftware.smack.XMPPException;
  38. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  39. import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
  40. import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
  41. import org.jivesoftware.smack.packet.IQ;
  42. import org.jivesoftware.smack.packet.IQ.Type;
  43. import org.jivesoftware.smack.util.SmackExecutorThreadFactory;
  44. import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
  45. import org.jivesoftware.smackx.ping.PingFailedListener;
  46. import org.jivesoftware.smackx.ping.packet.Ping;
  47. import org.jxmpp.jid.DomainBareJid;
  48. import org.jxmpp.jid.Jid;
  49. /**
  50. * Implements the XMPP Ping as defined by XEP-0199. The XMPP Ping protocol
  51. * allows one entity to ping any other entity by simply sending a ping to the
  52. * appropriate JID. PingManger also periodically sends XMPP pings to the server
  53. * to avoid NAT timeouts and to test the connection status.
  54. * <p>
  55. * The default server ping interval is 30 minutes and can be modified with
  56. * {@link #setDefaultPingInterval(int)} and {@link #setPingInterval(int)}.
  57. * </p>
  58. *
  59. * @author Florian Schmaus
  60. * @see <a href="http://www.xmpp.org/extensions/xep-0199.html">XEP-0199:XMPP
  61. * Ping</a>
  62. */
  63. public class MyPingManager extends Manager {
  64. private static final Logger LOGGER = Logger.getLogger(MyPingManager.class.getName());
  65. private static final Map<XMPPConnection, MyPingManager> INSTANCES = new WeakHashMap<XMPPConnection, MyPingManager>();
  66. static {
  67. XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
  68. public void connectionCreated(XMPPConnection connection) {
  69. getInstanceFor(connection);
  70. }
  71. });
  72. }
  73. /**
  74. * Retrieves a {@link MyPingManager} for the specified {@link XMPPConnection},
  75. * creating one if it doesn't already exist.
  76. *
  77. * @param connection
  78. * The connection the manager is attached to.
  79. * @return The new or existing manager.
  80. */
  81. public static MyPingManager getInstanceFor(XMPPConnection connection) {
  82. MyPingManager MyPingManager = INSTANCES.get(connection);
  83. if (MyPingManager == null) {
  84. MyPingManager = new MyPingManager(connection);
  85. INSTANCES.put(connection, MyPingManager);
  86. }
  87. return MyPingManager;
  88. }
  89. /**
  90. * The default ping interval in seconds used by new MyPingManager instances. The
  91. * default is 30 minutes.
  92. */
  93. private static int defaultPingInterval = 60 * 30;
  94. /**
  95. * Set the default ping interval which will be used for new connections.
  96. *
  97. * @param interval
  98. * the interval in seconds
  99. */
  100. public static void setDefaultPingInterval(int interval) {
  101. defaultPingInterval = interval;
  102. }
  103. private final Set<PingFailedListener> pingFailedListeners = Collections
  104. .synchronizedSet(new HashSet<PingFailedListener>());
  105. private final ScheduledExecutorService executorService;
  106. /**
  107. * The interval in seconds between pings are send to the users server.
  108. */
  109. private int pingInterval = defaultPingInterval;
  110. private ScheduledFuture<?> nextAutomaticPing;
  111. private MyPingManager(XMPPConnection connection) {
  112. super(connection);
  113. executorService = Executors
  114. .newSingleThreadScheduledExecutor(new SmackExecutorThreadFactory(connection, "Ping"));
  115. ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
  116. sdm.addFeature(Ping.NAMESPACE);
  117. connection.registerIQRequestHandler(
  118. new AbstractIqRequestHandler(Ping.ELEMENT, Ping.NAMESPACE, Type.get, Mode.async) {
  119. @Override
  120. public IQ handleIQRequest(IQ iqRequest) {
  121. Ping ping = (Ping) iqRequest;
  122. return ping.getPong();
  123. }
  124. });
  125. connection.addConnectionListener(new AbstractConnectionClosedListener() {
  126. @Override
  127. public void authenticated(XMPPConnection connection, boolean resumed) {
  128. maybeSchedulePingServerTask();
  129. }
  130. @Override
  131. public void connectionTerminated() {
  132. maybeStopPingServerTask();
  133. }
  134. });
  135. maybeSchedulePingServerTask();
  136. }
  137. /**
  138. * Pings the given jid. This method will return false if an error occurs. The
  139. * exception to this, is a server ping, which will always return true if the
  140. * server is reachable, event if there is an error on the ping itself (i.e. ping
  141. * not supported).
  142. * <p>
  143. * Use {@link #isPingSupported(String)} to determine if XMPP Ping is supported
  144. * by the entity.
  145. *
  146. * @param jid
  147. * The id of the entity the ping is being sent to
  148. * @param pingTimeout
  149. * The time to wait for a reply in milliseconds
  150. * @return true if a reply was received from the entity, false otherwise.
  151. * @throws NoResponseException
  152. * if there was no response from the jid.
  153. * @throws NotConnectedException
  154. */
  155. public boolean ping(DomainBareJid jid, long pingTimeout) throws NotConnectedException, NoResponseException {
  156. final XMPPConnection connection = connection();
  157. // Packet collector for IQs needs an connection that was at least authenticated
  158. // once,
  159. // otherwise the client JID will be null causing an NPE
  160. if (!connection.isAuthenticated()) {
  161. throw new NotConnectedException();
  162. }
  163. Ping ping = new Ping(jid);
  164. try {
  165. connection.createStanzaCollectorAndSend(ping).nextResultOrThrow(pingTimeout);
  166. } catch (XMPPException exc) {
  167. return jid.equals(connection.getServiceName());
  168. } catch (InterruptedException e) {
  169. // TODO Auto-generated catch block
  170. e.printStackTrace();
  171. }
  172. return true;
  173. }
  174. /**
  175. * Same as calling {@link #ping(String, long)} with the defaultpacket reply
  176. * timeout.
  177. *
  178. * @param jid
  179. * The id of the entity the ping is being sent to
  180. * @return true if a reply was received from the entity, false otherwise.
  181. * @throws NotConnectedException
  182. * @throws NoResponseException
  183. * if there was no response from the jid.
  184. */
  185. public boolean ping(DomainBareJid jid) throws NotConnectedException, NoResponseException {
  186. return ping(jid, connection().getPacketReplyTimeout());
  187. }
  188. /**
  189. * Query the specified entity to see if it supports the Ping protocol (XEP-0199)
  190. *
  191. * @param jid
  192. * The id of the entity the query is being sent to
  193. * @return true if it supports ping, false otherwise.
  194. * @throws XMPPErrorException
  195. * An XMPP related error occurred during the request
  196. * @throws NoResponseException
  197. * if there was no response from the jid.
  198. * @throws NotConnectedException
  199. */
  200. public boolean isPingSupported(Jid jid) throws NoResponseException, XMPPErrorException, NotConnectedException,InterruptedException {
  201. return ServiceDiscoveryManager.getInstanceFor(connection()).supportsFeature(jid, Ping.NAMESPACE);
  202. }
  203. /**
  204. * Pings the server. This method will return true if the server is reachable. It
  205. * is the equivalent of calling <code>ping</code> with the XMPP domain.
  206. * <p>
  207. * Unlike the {@link #ping(String)} case, this method will return true even if
  208. * {@link #isPingSupported(String)} is false.
  209. *
  210. * @return true if a reply was received from the server, false otherwise.
  211. * @throws NotConnectedException
  212. */
  213. public boolean pingMyServer() throws NotConnectedException {
  214. return pingMyServer(true);
  215. }
  216. /**
  217. * Pings the server. This method will return true if the server is reachable. It
  218. * is the equivalent of calling <code>ping</code> with the XMPP domain.
  219. * <p>
  220. * Unlike the {@link #ping(String)} case, this method will return true even if
  221. * {@link #isPingSupported(String)} is false.
  222. *
  223. * @param notifyListeners
  224. * Notify the PingFailedListener in case of error if true
  225. * @return true if the user's server could be pinged.
  226. * @throws NotConnectedException
  227. */
  228. public boolean pingMyServer(boolean notifyListeners) throws NotConnectedException {
  229. return pingMyServer(notifyListeners, connection().getPacketReplyTimeout());
  230. }
  231. /**
  232. * Pings the server. This method will return true if the server is reachable. It
  233. * is the equivalent of calling <code>ping</code> with the XMPP domain.
  234. * <p>
  235. * Unlike the {@link #ping(String)} case, this method will return true even if
  236. * {@link #isPingSupported(String)} is false.
  237. *
  238. * @param notifyListeners
  239. * Notify the PingFailedListener in case of error if true
  240. * @param pingTimeout
  241. * The time to wait for a reply in milliseconds
  242. * @return true if the user's server could be pinged.
  243. * @throws NotConnectedException
  244. */
  245. public boolean pingMyServer(boolean notifyListeners, long pingTimeout) throws NotConnectedException {
  246. boolean res;
  247. try {
  248. res = ping(connection().getServiceName(), pingTimeout);
  249. } catch (NoResponseException e) {
  250. res = false;
  251. }
  252. if (!res && notifyListeners) {
  253. for (PingFailedListener l : pingFailedListeners)
  254. l.pingFailed();
  255. }
  256. return res;
  257. }
  258. /**
  259. * Set the interval in seconds between a automated server ping is send. A
  260. * negative value disables automatic server pings. All settings take effect
  261. * immediately. If there is an active scheduled server ping it will be canceled
  262. * and, if <code>pingInterval</code> is positive, a new one will be scheduled in
  263. * pingInterval seconds.
  264. * <p>
  265. * If the ping fails after 3 attempts waiting the connections reply timeout for
  266. * an answer, then the ping failed listeners will be invoked.
  267. * </p>
  268. *
  269. * @param pingInterval
  270. * the interval in seconds between the automated server pings
  271. */
  272. public void setPingInterval(int pingInterval) {
  273. this.pingInterval = pingInterval;
  274. maybeSchedulePingServerTask();
  275. }
  276. /**
  277. * Get the current ping interval.
  278. *
  279. * @return the interval between pings in seconds
  280. */
  281. public int getPingInterval() {
  282. return pingInterval;
  283. }
  284. /**
  285. * Register a new PingFailedListener
  286. *
  287. * @param listener
  288. * the listener to invoke
  289. */
  290. public void registerPingFailedListener(PingFailedListener listener) {
  291. pingFailedListeners.add(listener);
  292. }
  293. /**
  294. * Unregister a PingFailedListener
  295. *
  296. * @param listener
  297. * the listener to remove
  298. */
  299. public void unregisterPingFailedListener(PingFailedListener listener) {
  300. pingFailedListeners.remove(listener);
  301. }
  302. private void maybeSchedulePingServerTask() {
  303. maybeSchedulePingServerTask(0);
  304. }
  305. /**
  306. * Cancels any existing periodic ping task if there is one and schedules a new
  307. * ping task if pingInterval is greater then zero.
  308. *
  309. * @param delta
  310. * the delta to the last received stanza in seconds
  311. */
  312. private void maybeSchedulePingServerTask(int delta) {
  313. maybeStopPingServerTask();
  314. if (pingInterval > 0) {
  315. int nextPingIn = pingInterval - delta;
  316. LOGGER.fine("Scheduling ServerPingTask in " + nextPingIn + " seconds (pingInterval=" + pingInterval
  317. + ", delta=" + delta + ")");
  318. nextAutomaticPing = executorService.schedule(pingServerRunnable, nextPingIn, TimeUnit.SECONDS);
  319. }
  320. }
  321. private void maybeStopPingServerTask() {
  322. if (nextAutomaticPing != null) {
  323. nextAutomaticPing.cancel(true);
  324. nextAutomaticPing = null;
  325. }
  326. }
  327. /**
  328. * Ping the server if deemed necessary because automatic server pings are
  329. * enabled ({@link #setPingInterval(int)}) and the ping interval has expired.
  330. */
  331. public void pingServerIfNecessary() {
  332. final int DELTA = 1000; // 1 seconds
  333. final int TRIES = 3; // 3 tries
  334. final XMPPConnection connection = connection();
  335. // final XMPPConnection connection = this.connection;
  336. if (connection == null) {
  337. // connection has been collected by GC
  338. // which means we can stop the thread by breaking the loop
  339. return;
  340. }
  341. if (pingInterval <= 0) {
  342. // Ping has been disabled
  343. return;
  344. }
  345. long lastStanzaReceived = connection.getLastStanzaReceived();
  346. if (lastStanzaReceived > 0) {
  347. long now = System.currentTimeMillis();
  348. // Delta since the last stanza was received
  349. int deltaInSeconds = (int) ((now - lastStanzaReceived) / 1000);
  350. // If the delta is small then the ping interval, then we can defer the ping
  351. if (deltaInSeconds < pingInterval) {
  352. maybeSchedulePingServerTask(deltaInSeconds);
  353. return;
  354. }
  355. }
  356. if (connection.isAuthenticated()) {
  357. boolean res = false;
  358. for (int i = 0; i < TRIES; i++) {
  359. if (i != 0) {
  360. try {
  361. Thread.sleep(DELTA);
  362. } catch (InterruptedException e) {
  363. // We received an interrupt
  364. // This only happens if we should stop pinging
  365. return;
  366. }
  367. }
  368. try {
  369. res = pingMyServer(false);
  370. /* Log.i("XMPP Ping", "result:"+res); */
  371. } catch (SmackException e) {
  372. LOGGER.log(Level.WARNING, "SmackError while pinging server", e);
  373. res = false;
  374. }
  375. // stop when we receive a pong back
  376. if (res) {
  377. break;
  378. }
  379. }
  380. if (!res) {
  381. for (PingFailedListener l : pingFailedListeners) {
  382. l.pingFailed();
  383. }
  384. } else {
  385. // Ping was successful, wind-up the periodic task again
  386. maybeSchedulePingServerTask();
  387. }
  388. } else {
  389. LOGGER.warning("XMPPConnection was not authenticated");
  390. }
  391. }
  392. private final Runnable pingServerRunnable = new Runnable() {
  393. public void run() {
  394. LOGGER.fine("ServerPingTask run()");
  395. pingServerIfNecessary();
  396. }
  397. };
  398. @Override
  399. protected void finalize() throws Throwable {
  400. LOGGER.fine("finalizing MyPingManager: Shutting down executor service");
  401. try {
  402. executorService.shutdown();
  403. } catch (Throwable t) {
  404. LOGGER.log(Level.WARNING, "finalize() threw throwable", t);
  405. } finally {
  406. super.finalize();
  407. }
  408. }
  409. }
  1. package com.testV3;
  2. public class Test3 {
  3. final static String USERNAME = "gm";
  4. final static String PASSWORD = "123456";
  5. final static String XMPPDOMAIN = "172.19.12.240";
  6. final static String SERVERNAME = "pc-20170308pkrs";
  7. public static void main(String[] args) {
  8. // TODO Auto-generated method stub
  9. String[] nodeId = {"/BAGGL/GJXX/LCGJ","/BAGGL/GJXX/TLGJ"};
  10. SubscribeThread smark = new SubscribeThread(USERNAME,PASSWORD,XMPPDOMAIN,SERVERNAME,nodeId,new MyItemEventListener());
  11. smark.start();
  12. }
  13. }

XMPP中的订阅流程

1、首先,需要确认你的服务器支持pubsub特性

1.1  查询XMPP服务的所有服务
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <iq to="pc-20170308pkrs" id="3EV56-7" type="get">
  3. <query xmlns="http://jabber.org/protocol/disco#info"></query>
  4. </iq>
返回:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <iq type="result" id="3EV56-7" from="pc-20170308pkrs" to="gm@pc-20170308pkrs/pc">
  3. <query xmlns="http://jabber.org/protocol/disco#info">
  4. <identity category="server" name="Openfire Server" type="im"/>
  5. <identity category="pubsub" type="pep"/>
  6. <feature var="http://jabber.org/protocol/pubsub#retrieve-default"/>
  7. <feature var="http://jabber.org/protocol/pubsub#purge-nodes"/>
  8. <feature var="vcard-temp"/>
  9. <feature var="http://jabber.org/protocol/pubsub#subscribe"/>
  10. <feature var="http://jabber.org/protocol/pubsub#subscription-options"/>
  11. <feature var="http://jabber.org/protocol/pubsub#create-nodes"/>
  12. <feature var="http://jabber.org/protocol/pubsub#outcast-affiliation"/>
  13. <feature var="msgoffline"/>
  14. <feature var="http://jabber.org/protocol/pubsub#get-pending"/>
  15. <feature var="http://jabber.org/protocol/pubsub#multi-subscribe"/>
  16. <feature var="http://jabber.org/protocol/pubsub#presence-notifications"/>
  17. <feature var="urn:xmpp:ping"/>
  18. <feature var="jabber:iq:register"/>
  19. <feature var="http://jabber.org/protocol/pubsub#delete-nodes"/>
  20. <feature var="http://jabber.org/protocol/pubsub#config-node"/>
  21. <feature var="http://jabber.org/protocol/pubsub#retrieve-items"/>
  22. <feature var="http://jabber.org/protocol/pubsub#auto-create"/>
  23. <feature var="http://jabber.org/protocol/disco#items"/>
  24. <feature var="http://jabber.org/protocol/pubsub#item-ids"/>
  25. <feature var="http://jabber.org/protocol/pubsub#meta-data"/>
  26. <feature var="jabber:iq:roster"/>
  27. <feature var="http://jabber.org/protocol/pubsub#instant-nodes"/>
  28. <feature var="http://jabber.org/protocol/pubsub#modify-affiliations"/>
  29. <feature var="http://jabber.org/protocol/pubsub#persistent-items"/>
  30. <feature var="http://jabber.org/protocol/pubsub#create-and-configure"/>
  31. <feature var="http://jabber.org/protocol/pubsub"/>
  32. <feature var="http://jabber.org/protocol/pubsub#publisher-affiliation"/>
  33. <feature var="http://jabber.org/protocol/pubsub#access-open"/>
  34. <feature var="http://jabber.org/protocol/pubsub#retrieve-affiliations"/>
  35. <feature var="jabber:iq:version"/>
  36. <feature var="http://jabber.org/protocol/pubsub#retract-items"/>
  37. <feature var="urn:xmpp:time"/>
  38. <feature var="http://jabber.org/protocol/pubsub#manage-subscriptions"/>
  39. <feature var="jabber:iq:privacy"/>
  40. <feature var="jabber:iq:last"/>
  41. <feature var="http://jabber.org/protocol/commands"/>
  42. <feature var="http://jabber.org/protocol/offline"/>
  43. <feature var="urn:xmpp:carbons:2"/>
  44. <feature var="http://jabber.org/protocol/address"/>
  45. <feature var="http://jabber.org/protocol/pubsub#publish"/>
  46. <feature var="http://jabber.org/protocol/pubsub#collections"/>
  47. <feature var="http://jabber.org/protocol/pubsub#retrieve-subscriptions"/>
  48. <feature var="http://jabber.org/protocol/disco#info"/>
  49. <feature var="jabber:iq:private"/>
  50. <feature var="http://jabber.org/protocol/rsm"/>
  51. </query>
  52. </iq>
1.2 查询发布订阅中的某一个持久化的叶子节点
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <iq to="pubsub.pc-20170308pkrs" id="3EV56-9" type="get">
  3. <query xmlns="http://jabber.org/protocol/disco#info" node="/BAGGL/GJXX/LCGJ"></query>
  4. </iq>
返回
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <iq type="result" id="3EV56-9" from="pubsub.pc-20170308pkrs" to="gm@pc-20170308pkrs/pc">
  3. <query xmlns="http://jabber.org/protocol/disco#info" node="/BAGGL/GJXX/LCGJ">
  4. <identity category="pubsub" type="leaf"/>
  5. <feature var="http://jabber.org/protocol/pubsub"/>
  6. <feature var="http://jabber.org/protocol/disco#info"/>
  7. <x xmlns="jabber:x:data" type="result">
  8. <field var="FORM_TYPE" type="hidden">
  9. <value>http://jabber.org/protocol/pubsub#meta-data</value>
  10. </field>
  11. <field var="pubsub#title" type="text-single" label="Short name for the node">
  12. <value>流程告警</value>
  13. </field>
  14. <field var="pubsub#description" type="text-single" label="Description of the node">
  15. <value></value>
  16. </field>
  17. <field var="pubsub#node_type" type="text-single" label="Whether the node is a leaf (default) or a collection">
  18. <value>leaf</value>
  19. </field>
  20. <field var="pubsub#collection" type="text-single" label="The collection with which a node is affiliated."/>
  21. <field var="pubsub#subscribe" type="boolean" label="Allow subscriptions to node">
  22. <value>1</value>
  23. </field>
  24. <field var="pubsub#subscription_required" type="boolean" label="New subscriptions require configuration">
  25. <value>0</value>
  26. </field>
  27. <field var="pubsub#deliver_payloads" type="boolean" label="Deliver payloads with event notifications">
  28. <value>1</value>
  29. </field>
  30. <field var="pubsub#notify_config" type="boolean" label="Notify subscribers when the node configuration changes">
  31. <value>1</value>
  32. </field>
  33. <field var="pubsub#notify_delete" type="boolean" label="Notify subscribers when the node is deleted">
  34. <value>1</value>
  35. </field>
  36. <field var="pubsub#notify_retract" type="boolean" label="Notify subscribers when items are removed from the node">
  37. <value>1</value>
  38. </field>
  39. <field var="pubsub#presence_based_delivery" type="boolean" label="Only deliver notifications to available users">
  40. <value>0</value>
  41. </field>
  42. <field var="pubsub#type" type="text-single" label="Type of payload data to be provided at this node">
  43. <value></value>
  44. </field>
  45. <field var="pubsub#body_xslt" type="text-single" label="Message body XSLT">
  46. <value>/BAGGL/GJXX/LCGJ</value>
  47. </field>
  48. <field var="pubsub#dataform_xslt" type="text-single" label="Payload XSLT">
  49. <value></value>
  50. </field>
  51. <field var="pubsub#access_model" type="list-single" label="Specify who may subscribe and retrieve items">
  52. <option>
  53. <value>authorize</value>
  54. </option>
  55. <option>
  56. <value>open</value>
  57. </option>
  58. <option>
  59. <value>presence</value>
  60. </option>
  61. <option>
  62. <value>roster</value>
  63. </option>
  64. <option>
  65. <value>whitelist</value>
  66. </option>
  67. <value>open</value>
  68. </field>
  69. <field var="pubsub#publish_model" type="list-single" label="Publisher model">
  70. <option>
  71. <value>publishers</value>
  72. </option>
  73. <option>
  74. <value>subscribers</value>
  75. </option>
  76. <option>
  77. <value>open</value>
  78. </option>
  79. <value>open</value>
  80. </field>
  81. <field var="pubsub#roster_groups_allowed" type="list-multi" label="Roster groups allowed to subscribe"/>
  82. <field var="pubsub#contact" type="jid-multi" label="People to contact with questions"/>
  83. <field var="pubsub#language" type="text-single" label="Default language">
  84. <value>English</value>
  85. </field>
  86. <field var="pubsub#owner" type="jid-multi" label="Node owners">
  87. <value>admin@pc-20170308pkrs</value>
  88. </field>
  89. <field var="pubsub#publisher" type="jid-multi" label="Node publishers"/>
  90. <field var="pubsub#itemreply" type="list-single" label="Select entity that should receive replies to items">
  91. <option>
  92. <value>owner</value>
  93. </option>
  94. <option>
  95. <value>publisher</value>
  96. </option>
  97. <value>owner</value>
  98. </field>
  99. <field var="pubsub#replyroom" type="jid-multi" label="Multi-user chat room to which replies should be sent"/>
  100. <field var="pubsub#replyto" type="jid-multi" label="Users to which replies should be sent"/>
  101. <field var="pubsub#send_item_subscribe" type="boolean" label="Send items to new subscribers">
  102. <value>1</value>
  103. </field>
  104. <field var="pubsub#persist_items" type="boolean" label="Persist items to storage">
  105. <value>1</value>
  106. </field>
  107. <field var="pubsub#max_items" type="text-single" label="Max number of items to persist">
  108. <value>100000</value>
  109. </field>
  110. <field var="pubsub#max_payload_size" type="text-single" label="Max payload size in bytes">
  111. <value>5120</value>
  112. </field>
  113. </x>
  114. </query>
  115. </iq>
1.3 订阅消息到达
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <message from="pubsub.pc-20170308pkrs" to="gm@pc-20170308pkrs" id="N5K5HEvD">
  3. <event xmlns="http://jabber.org/protocol/pubsub#event">
  4. <items node="/BAGGL/GJXX/LCGJ">
  5. <item id="1528350475613">
  6. <pubmessage xmlns="pub:message">
  7. <topic>/BAGGL/GJXX/LCGJ</topic>
  8. <messageid>1528350475613</messageid>
  9. <content>流程告警193</content>
  10. </pubmessage>
  11. </item>
  12. </items>
  13. </event>
  14. <headers xmlns="http://jabber.org/protocol/shim">
  15. <header name="SubID">A5OJTdo105AM4hNOhMeNRvKiVelT2CAMCGb9NYxC</header>
  16. </headers>
  17. <delay xmlns="urn:xmpp:delay" stamp="2018-06-07T05:47:55.676Z" from="pc-20170308pkrs"></delay>
  18. </message>

XMPP即时通讯协议使用(三)——订阅发布、断开重连与Ping的更多相关文章

  1. XMPP即时通讯协议使用(前传)——协议详解

    XMPP详解 XMPP(eXtensible Messaging and Presence Protocol,可扩展消息处理和现场协议)是一种在两个地点间传递小型结构化数据的协议.在此基础上,XMPP ...

  2. XMPP即时通讯协议使用(四)——Openfire服务器源码编译与添加消息记录保存

    下载Openfire源码 下载地址:https://www.igniterealtime.org/downloads/index.jsp,当前最新版本为:4.2.3 Eclipse上部署Openfir ...

  3. XMPP即时通讯协议使用(八)——基于订阅发布实现消息流转业务泳道图

  4. XMPP即时通讯协议使用(七)——利用Strophe实现WebIM及strophe.plugins插件使用

    Strophe简介与Openfire配置 Strophe.js是为XMPP写的一个js类库.因为http协议本身不能实现持久连接,所以strophe利用BOSH模拟实现持久连接. 官方文档: http ...

  5. XMPP即时通讯协议使用(六)——开发Openfire聊天记录插件

    转载地址:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 开发环境: Sys ...

  6. XMPP即时通讯协议使用(十)——好友关系状态

    sub  ask  recv 订阅 询问 接受 含义 substatus -1-  应该删除这个好友          Indicates that the roster item should be ...

  7. xmpp即时通讯协议的特性---长处和缺点!

    xmpp协议的定义? XMPP是一种基于标准通用标记语言的子集XML的协议,它继承了在XML环境中灵活的发展性. 因此.基于XMPP的应用具有超强的可扩展性.经过扩展以后的XMPP能够通过发送扩展的信 ...

  8. XMPP即时通讯协议使用(二)——基于Smack相关操作

    package com.test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator ...

  9. XMPP即时通讯协议使用(十二)——基于xmpp搭建简单的局域网WebRTC

    创建HTML和JS ofwebrtc.html <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" ...

随机推荐

  1. git 操作遇到的问题与解决方法

    一.使用git在本地创建一个项目的过程,Git 上传本地文件到github $ makdir ~/hello-world //创建一个项目hello-world $ cd ~/hello-world ...

  2. 如何对Web服务器进行飓风级防御

    万一你的网站被DDOS飓风式攻击,你会怎么办?笔者以经验告诉你,这里的每一层都起着保护网站的作用.如果您宁愿拥有如何在单台服务器上维持大量流量的版本,则可以: 专用硬件服务器,无共享主机 千兆上行链路 ...

  3. xcode7 添加个人账户 is not on any development teams

    XCODE7已经可以免费真机测试, 但添加个人账户后,显示 is not on any development teams , 解决办法: 点击 “-” 删除当前账户,退出XCODE重新打开再添加即可 ...

  4. luoguP4721 【模板】分治 FFT (分治NTT)

    给定 $g[1....n-1]$,求 $f[0],f[1],...,f[n-1]$,其中   $f[i]=\sum_{j=1}^{i}f[i-j]g[j]$    变界为 $f[0]=1$ 答案模 9 ...

  5. 【Java】java.sql.SQLDataException: Cannot determine value type from string

    报错如下: There was an unexpected error (type=Internal Server Error, status=500). Error attempting to ge ...

  6. Jenkins slave-agent.jnlp运行无反应

    在配置Jenkins的Windows节点时候,点击slave-agent.jnlp选择javaws.exe运行无反应,cmd命令执行javaws slave-agent.jnlp也不行,slave-a ...

  7. 用 margin 还是用 padding ?

    边界(margin):元素周围生成额外的空白区."空白区"通常是指其他元素不能出现且父元素背景可见的区域. 补白(padding):补白位于元素框的边界与内容区之间.很自然,用于影 ...

  8. 腾讯云服务器centos通过yum安装mysql数据库

    安装mysql有两种: 1-可以使用yum安装, 2-可以自己下载安装包安装mysql, 腾讯云的centos系统自带了yum,所以用yum安装方便点 安装步骤 1-查看yum源中是否有mysql y ...

  9. DHCP服务器怎么设置怎么启动

    DHCP:动态主机配置协议,服务器用于为网络中的客户端自动分配IP地址.这种方法避免了由于手动配置IP地址导致的IP地址冲突问题,同时也减少了网络管理员的工作量. 工具/原料 在配置DHCP服务器时, ...

  10. Centos7.6 安装

    序:在“Intel 英特尔 NUC6I7KYK 迷你主机” 上 安装“Centos7.6” 一.制作U盘启动盘 参考<制作CentOS的U盘启动盘>.<制作 CentOS7的U盘系统 ...