Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 连接排空后打开新连接。谷歌云消息_Java_Spring Mvc_Google Cloud Messaging - Fatal编程技术网

Java 连接排空后打开新连接。谷歌云消息

Java 连接排空后打开新连接。谷歌云消息,java,spring-mvc,google-cloud-messaging,Java,Spring Mvc,Google Cloud Messaging,我对谷歌云消息有些陌生。我们已经使用它几个月了,但就在最近,我们收到了“连接耗尽”的消息。发生这种情况时,所有通信都停止 谷歌表示: 当您收到连接消息时,您应该 立即开始向另一个CCS连接发送消息,打开 如有必要,请重新连接。然而,你应该保留原稿 连接打开并继续接收可能通过 连接(并确认)-CCS将处理启动连接 准备好后关闭 我的问题是 如果我手动打开一个新连接,如果我不关闭现有连接,它如何知道要使用哪个连接 如果同时发送6条消息,如何阻止该方法打开6个连接?还是我对此感到困惑 为什么会发生连接

我对谷歌云消息有些陌生。我们已经使用它几个月了,但就在最近,我们收到了“连接耗尽”的消息。发生这种情况时,所有通信都停止

谷歌表示:

当您收到连接消息时,您应该 立即开始向另一个CCS连接发送消息,打开 如有必要,请重新连接。然而,你应该保留原稿 连接打开并继续接收可能通过 连接(并确认)-CCS将处理启动连接 准备好后关闭

我的问题是

  • 如果我手动打开一个新连接,如果我不关闭现有连接,它如何知道要使用哪个连接
  • 如果同时发送6条消息,如何阻止该方法打开6个连接?还是我对此感到困惑
  • 为什么会发生连接排水
  • 我感到惊讶的是,他们的示例代码中还没有用到这一点。看起来这几乎是你所需要的一切。代码中是否已经为我完成了,而我却错过了它

    我的代码中没有main方法,而是使用servlet作为触发器。我的联系是这样开始的

    @PostConstruct
        public void init() throws Exception{
            try {
                smackCcsClient.connect(Long.parseLong(env.getProperty("gcm.api")), env.getProperty("gcm.key"));
            }catch (IOException e ){
                e.printStackTrace();
            }catch(SmackException e){
                e.printStackTrace();
            }catch(XMPPException e){
                e.printStackTrace();
            }
        }
    
    然而,在这之后,我再也没有接触过连接。我是否处理错了,连接是我应该更频繁接触的还是我需要跟踪的

    _______________________在问题后加上_________________________

    我在他们的示例代码中添加了一个连接,以尝试重新初始化连接。看起来是这样的:

    if ("CONNECTION_DRAINING".equals(controlType)) {
                connectionDraining = true;
                //Open new connection because old connection will be closing or is already closed.
                try {
                    connect(Long.parseLong(env.getProperty("gcm.api")), env.getProperty("gcm.key"));
                } catch (XMPPException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (SmackException e) {
                    e.printStackTrace();
                }
    
            } else {
                logger.log(Level.INFO, "Unrecognized control type: %s. This could happen if new features are " + "added to the CCS protocol.",
                        controlType);
            }
    

    我也是GCM新手,面临着同样的问题……我通过在连接消息上创建新的smackcsclient()解决了这个问题。旧连接应仍然存在并接收消息,但不发送,因为:

    受保护的易失性布尔连接训练=真

    谷歌表示连接将被CCS关闭:

    CCS将在连接准备就绪时启动连接关闭

    在CCS关闭连接之前,您将能够从两个连接接收消息,但只能使用新的连接发送消息。当旧连接被关闭时,它应该被销毁,我不确定是否调用了垃圾收集器…试图解决这个问题


    注:我对这个答案不是100%肯定,但也许它会为讨论打开更多的空间。

    我已经编写了处理此类情况的代码(基本上是将新的下游消息转移到新的连接)。。。没有经过彻底的测试

    import java.util.Deque;
    导入java.util.HashMap;
    导入java.util.Map;
    导入java.util.concurrent.concurrentLinkedQue;
    导入javax.net.ssl.SSLSocketFactory;
    导入org.jivesoftware.smack.ConnectionConfiguration;
    导入org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
    导入org.jivesoftware.smack.ConnectionListener;
    导入org.jivesoftware.smack.PacketInterceptor;
    导入org.jivesoftware.smack.PacketListener;
    导入org.jivesoftware.smack.SmackException.NotConnectedException;
    导入org.jivesoftware.smack.XMPPConnection;
    导入org.jivesoftware.smack.filter.PacketTypeFilter;
    导入org.jivesoftware.smack.packet.DefaultPacketExtension;
    导入org.jivesoftware.smack.packet.Message;
    导入org.jivesoftware.smack.packet.packet;
    导入org.jivesoftware.smack.packet.PacketExtension;
    导入org.jivesoftware.smack.provider.PacketExtensionProvider;
    导入org.jivesoftware.smack.provider.ProviderManager;
    导入org.jivesoftware.smack.tcp.XMPPTCPConnection;
    导入org.jivesoftware.smack.util.StringUtils;
    导入org.slf4j.Logger;
    导入org.slf4j.LoggerFactory;
    导入org.xmlpull.v1.XmlPullParser;
    导入com.fasterxml.jackson.core.type.TypeReference;
    /**
    *基于https://developer.android.com/google/gcm/ccs.html#smack
    * 
    *@author Abhinav.Dwivedi
    *
    */
    公共类SmackCcsClient实现CCSCClient{
    私有静态最终记录器Logger=LoggerFactory.getLogger(smackcsclient.class);
    私有静态最终字符串GCM_SERVER=“GCM.googleapis.com”;
    专用静态最终int GCM_端口=5235;
    私有静态最终字符串GCM\u元素\u NAME=“GCM”;
    私有静态最终字符串GCM_NAMESPACE=“google:mobile:data”;
    私有静态客户端实例;
    静止的{
    addExtensionProvider(GCM_元素_名称、GCM_命名空间、新PacketExtensionProvider(){
    @凌驾
    公共PacketExtension parseExtension(XmlPullParser parser)引发异常{
    字符串json=parser.nextText();
    返回新的gcmpacktextension(json);
    }
    });
    }
    私人频道;
    公共静态SmackCcsClient实例(){
    if(实例==null){
    已同步(smackcsclient.class){
    if(实例==null){
    实例=新的SMACKCCClient();
    }
    }
    }
    返回实例;
    }
    私有SmackCcsClient(){
    通道=新的ConcurrentLinkedQue();
    channels.addFirst(connect());
    }
    私有类频道{
    专用XMPPConnection连接;
    /**
    *指示连接是否处于排放状态,这意味着它将不接受任何新的下游
    *信息。
    */
    private volatile boolean connectionTraining=false;
    /**
    *发送包含所提供内容的数据包。
    */
    私有void发送(字符串jsonRequest)抛出NotConnectedException{
    数据包请求=新的gcmpacktextension(jsonRequest).toPacket();
    发送数据包(请求);
    }
    私有void handleControlMessage(映射jsonObject){
    debug(“handleControlMessage():{}”,jsonObject);
    String controlType=(String)jsonObject.get(“控件_
    
    import java.util.Deque;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.ConcurrentLinkedDeque;
    
    import javax.net.ssl.SSLSocketFactory;
    
    import org.jivesoftware.smack.ConnectionConfiguration;
    import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
    import org.jivesoftware.smack.ConnectionListener;
    import org.jivesoftware.smack.PacketInterceptor;
    import org.jivesoftware.smack.PacketListener;
    import org.jivesoftware.smack.SmackException.NotConnectedException;
    import org.jivesoftware.smack.XMPPConnection;
    import org.jivesoftware.smack.filter.PacketTypeFilter;
    import org.jivesoftware.smack.packet.DefaultPacketExtension;
    import org.jivesoftware.smack.packet.Message;
    import org.jivesoftware.smack.packet.Packet;
    import org.jivesoftware.smack.packet.PacketExtension;
    import org.jivesoftware.smack.provider.PacketExtensionProvider;
    import org.jivesoftware.smack.provider.ProviderManager;
    import org.jivesoftware.smack.tcp.XMPPTCPConnection;
    import org.jivesoftware.smack.util.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.xmlpull.v1.XmlPullParser;
    
    import com.fasterxml.jackson.core.type.TypeReference;
    
    
    /**
     * Based on https://developer.android.com/google/gcm/ccs.html#smack
     * 
     * @author Abhinav.Dwivedi
     *
     */
    public class SmackCcsClient implements CcsClient {
        private static final Logger logger = LoggerFactory.getLogger(SmackCcsClient.class);
        private static final String GCM_SERVER = "gcm.googleapis.com";
        private static final int GCM_PORT = 5235;
        private static final String GCM_ELEMENT_NAME = "gcm";
        private static final String GCM_NAMESPACE = "google:mobile:data";
        private static volatile SmackCcsClient instance;
        static {
            ProviderManager.addExtensionProvider(GCM_ELEMENT_NAME, GCM_NAMESPACE, new PacketExtensionProvider() {
                @Override
                public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
                    String json = parser.nextText();
                    return new GcmPacketExtension(json);
                }
            });
        }
        private final Deque<Channel> channels;
    
        public static SmackCcsClient instance() {
            if (instance == null) {
                synchronized (SmackCcsClient.class) {
                    if (instance == null) {
                        instance = new SmackCcsClient();
                    }
                }
            }
            return instance;
        }
    
        private SmackCcsClient() {
            channels = new ConcurrentLinkedDeque<Channel>();
            channels.addFirst(connect());
        }
    
        private class Channel {
            private XMPPConnection connection;
            /**
             * Indicates whether the connection is in draining state, which means that it will not accept any new downstream
             * messages.
             */
            private volatile boolean connectionDraining = false;
    
            /**
             * Sends a packet with contents provided.
             */
            private void send(String jsonRequest) throws NotConnectedException {
                Packet request = new GcmPacketExtension(jsonRequest).toPacket();
                connection.sendPacket(request);
            }
    
            private void handleControlMessage(Map<String, Object> jsonObject) {
                logger.debug("handleControlMessage(): {}", jsonObject);
                String controlType = (String) jsonObject.get("control_type");
                if ("CONNECTION_DRAINING".equals(controlType)) {
                    connectionDraining = true;
                } else {
                    logger.info("Unrecognized control type: {}. This could happen if new features are "
                            + "added to the CCS protocol.", controlType);
                }
            }
        }
    
        /**
         * Sends a downstream message to GCM.
         *
         */
        @Override
        public void sendDownstreamMessage(String message) throws Exception {
            Channel channel = channels.peekFirst();
            if (channel.connectionDraining) {
                synchronized (channels) {
                    channel = channels.peekFirst();
                    if (channel.connectionDraining) {
                        channels.addFirst(connect());
                        channel = channels.peekFirst();
                    }
                }
            }
            channel.send(message);
            logger.debug("Message Sent via CSS: ({})", message);
        }
    
        /**
         * Handles an upstream data message from a device application.
         *
         */
        protected void handleUpstreamMessage(Map<String, Object> jsonObject) {
            // PackageName of the application that sent this message.
            String category = (String) jsonObject.get("category");
            String from = (String) jsonObject.get("from");
            @SuppressWarnings("unchecked")
            Map<String, String> payload = (Map<String, String>) jsonObject.get("data");
            logger.info("Message received from device: category ({}), from ({}), payload: ({})", category, from,
                    JsonUtil.toJson(payload));
        }
    
        /**
         * Handles an ACK.
         *
         * <p>
         * Logs a INFO message, but subclasses could override it to properly handle ACKs.
         */
        public void handleAckReceipt(Map<String, Object> jsonObject) {
            String messageId = (String) jsonObject.get("message_id");
            String from = (String) jsonObject.get("from");
            logger.debug("handleAckReceipt() from: {}, messageId: {}", from, messageId);
        }
    
        /**
         * Handles a NACK.
         *
         * <p>
         * Logs a INFO message, but subclasses could override it to properly handle NACKs.
         */
        protected void handleNackReceipt(Map<String, Object> jsonObject) {
            String messageId = (String) jsonObject.get("message_id");
            String from = (String) jsonObject.get("from");
            logger.debug("handleNackReceipt() from: {}, messageId: ", from, messageId);
        }
    
        /**
         * Creates a JSON encoded ACK message for an upstream message received from an application.
         *
         * @param to
         *            RegistrationId of the device who sent the upstream message.
         * @param messageId
         *            messageId of the upstream message to be acknowledged to CCS.
         * @return JSON encoded ack.
         */
        protected static String createJsonAck(String to, String messageId) {
            Map<String, Object> message = new HashMap<String, Object>();
            message.put("message_type", "ack");
            message.put("to", to);
            message.put("message_id", messageId);
            return JsonUtil.toJson(message);
        }
    
        /**
         * Connects to GCM Cloud Connection Server using the supplied credentials.
         * 
         * @return
         */
        @Override
        public Channel connect() {
            try {
                Channel channel = new Channel();
                ConnectionConfiguration config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
                config.setSecurityMode(SecurityMode.enabled);
                config.setReconnectionAllowed(true);
                config.setRosterLoadedAtLogin(false);
                config.setSendPresence(false);
                config.setSocketFactory(SSLSocketFactory.getDefault());
    
                channel.connection = new XMPPTCPConnection(config);
                channel.connection.connect();
    
                channel.connection.addConnectionListener(new LoggingConnectionListener());
    
                // Handle incoming packets
                channel.connection.addPacketListener(new PacketListener() {
                    @Override
                    public void processPacket(Packet packet) {
                        logger.debug("Received: ({})", packet.toXML());
                        Message incomingMessage = (Message) packet;
                        GcmPacketExtension gcmPacket = (GcmPacketExtension) incomingMessage.getExtension(GCM_NAMESPACE);
                        String json = gcmPacket.getJson();
                        try {
                            Map<String, Object> jsonObject = JacksonUtil.DEFAULT.mapper().readValue(json,
                                    new TypeReference<Map<String, Object>>() {});
                            // present for ack, nack and control, null otherwise
                            Object messageType = jsonObject.get("message_type");
                            if (messageType == null) {
                                // Normal upstream data message
                                handleUpstreamMessage(jsonObject);
                                // Send ACK to CCS
                                String messageId = (String) jsonObject.get("message_id");
                                String from = (String) jsonObject.get("from");
                                String ack = createJsonAck(from, messageId);
                                channel.send(ack);
                            } else if ("ack".equals(messageType.toString())) {
                                // Process Ack
                                handleAckReceipt(jsonObject);
                            } else if ("nack".equals(messageType.toString())) {
                                // Process Nack
                                handleNackReceipt(jsonObject);
                            } else if ("control".equals(messageType.toString())) {
                                // Process control message
                                channel.handleControlMessage(jsonObject);
                            } else {
                                logger.error("Unrecognized message type ({})", messageType.toString());
                            }
                        } catch (Exception e) {
                            logger.error("Failed to process packet ({})", packet.toXML(), e);
                        }
                    }
                }, new PacketTypeFilter(Message.class));
    
                // Log all outgoing packets
                channel.connection.addPacketInterceptor(new PacketInterceptor() {
                    @Override
                    public void interceptPacket(Packet packet) {
                        logger.debug("Sent: {}", packet.toXML());
                    }
                }, new PacketTypeFilter(Message.class));
    
                channel.connection.login(ExternalConfig.gcmSenderId() + "@gcm.googleapis.com", ExternalConfig.gcmApiKey());
                return channel;
            } catch (Exception e) {
                logger.error(Logging.FATAL, "Error in creating channel for GCM communication", e);
                throw new RuntimeException(e);
            }
        }
    
        /**
         * XMPP Packet Extension for GCM Cloud Connection Server.
         */
        private static final class GcmPacketExtension extends DefaultPacketExtension {
    
            private final String json;
    
            public GcmPacketExtension(String json) {
                super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
                this.json = json;
            }
    
            public String getJson() {
                return json;
            }
    
            @Override
            public String toXML() {
                return String.format("<%s xmlns=\"%s\">%s</%s>", GCM_ELEMENT_NAME, GCM_NAMESPACE,
                        StringUtils.escapeForXML(json), GCM_ELEMENT_NAME);
            }
    
            public Packet toPacket() {
                Message message = new Message();
                message.addExtension(this);
                return message;
            }
        }
    
        private static final class LoggingConnectionListener implements ConnectionListener {
    
            @Override
            public void connected(XMPPConnection xmppConnection) {
                logger.info("Connected.");
            }
    
            @Override
            public void authenticated(XMPPConnection xmppConnection) {
                logger.info("Authenticated.");
            }
    
            @Override
            public void reconnectionSuccessful() {
                logger.info("Reconnecting..");
            }
    
            @Override
            public void reconnectionFailed(Exception e) {
                logger.error("Reconnection failed.. ", e);
            }
    
            @Override
            public void reconnectingIn(int seconds) {
                logger.info("Reconnecting in {} secs", seconds);
            }
    
            @Override
            public void connectionClosedOnError(Exception e) {
                logger.info("Connection closed on error.");
            }
    
            @Override
            public void connectionClosed() {
                logger.info("Connection closed.");
            }
        }
    }