Smack 4.1.0 GCM CCS一段时间后停止响应

时间:2016-04-04 08:48:37

标签: java google-cloud-messaging smack

为聊天模块实施了gcm ccs,我可以发送和接收消息。下面是主要的连接模块,

        config = XMPPTCPConnectionConfiguration.builder()
                .setServiceName("gcm-pesu.googleapis.com")
                .setPort(GCM_PORT)
                .setHost(GCM_SERVER)
                .setCompressionEnabled(false)
                .setConnectTimeout(30000)
                .setSecurityMode(SecurityMode.ifpossible)
                .setSendPresence(false)
                .setSocketFactory(SSLSocketFactory.getDefault())
                .build();

        connection = new XMPPTCPConnection(config);
        connection.connect();

        Roster roster = Roster.getInstanceFor(connection);
        roster.setRosterLoadedAtLogin(false);

        connection.addConnectionListener(new LoggingConnectionListener());

        // Handle incoming packets
        connection.addAsyncStanzaListener(new MyStanzaListener(), new MyStanzaFilter());

        // Log all outgoing packets
        connection.addPacketInterceptor(new MyStanzaInterceptor(), new MyStanzaFilter());

        connection.login(mProjectId + "@gcm.googleapis.com", mApiKey);
        logger.info("logged in: " + mProjectId);

        PingManager pm = PingManager.getInstanceFor(connection);
        pm.setPingInterval(300);
        pm.pingMyServer();
        pm.registerPingFailedListener(new PingFailedListener() {
            @Override
            public void pingFailed() {
                connection.disconnect();
                logger.error("GCM CCS, Ping failed !!");
            }
        });

我遇到的问题是没有收到来自GCM的任何消息,一段时间后由客户端设备发送。虽然,心跳看起来很正常,但即使在那种情况下,我也会从GCM获得乒乓球。这与SSL有关吗?

如下处理连接排水情况,

        String controlType = (String) jsonObject.get("control_type");
        volatile boolean connectionDraining = false;
        if ("CONNECTION_DRAINING".equals(controlType)) {
            connectionDraining = true;
            try {
                connection.disconnect();
                connect();
                connectionDraining = false;
            } catch (Exception e) {
                logger.error("Error establishing new connection after draining ", e);
            }
        }

2 个答案:

答案 0 :(得分:1)

当其中一个渠道耗尽时实施渠道队列。

            private Deque<Channel> channels;
            protected void handleControlMessage(Map<String, Object> jsonObject) {
            logger.info("Control message : " + jsonObject);
            String controlType = (String) jsonObject.get("control_type");
            if ("CONNECTION_DRAINING".equals(controlType)) {
                connectionDraining = true;
            } 
        }

发送消息时创建新频道

        public void sendDownstreamMessage(String jsonRequest) {
        Channel channel = channels.peekFirst();
        try {
            if (channel.connectionDraining) {
                synchronized (channels) {
                    channel = channels.peekFirst();
                    if (channel.connectionDraining) {
                        channels.addFirst(connect());
                        channel = channels.peekFirst();
                    }
                }
            }
            channel.send(jsonRequest);
        } catch (Exception e) {
            logger.error("Message not sent. Error in connecting :", e);
        }
    }

GCM将负责关闭另一个。这解决了这个问题。

答案 1 :(得分:0)

我相信你正面临一个使用gcm css的常见案例,这在文档中并不常见。 如果你查看文档Control Messages,你会看到:

  

CCS需要定期关闭连接以执行负载平衡。在关闭连接之前,CCS发送CONNECTION_DRAINING消息以指示连接正在耗尽,并将很快关闭。 “排水”是指关闭进入连接的消息流,但允许管道中已有的任何内容继续。收到CONNECTION_DRAINING消息时,应立即开始向另一个CCS连接发送消息,必要时打开新连接。但是,您应该保持原始连接处于打开状态并继续接收可能通过连接传递的消息(并确认它们)-CCS处理准备就绪时启动连接。