2017-05-03 131 views
1

我在发送iOS设备的批量通知时遇到问题,当我发送一些设备(多于或少于1-20个)时,它可以正常工作,但是当我必须发送批量发送3000+),它给我以下错误:发送批量iOS通知的问题

[2017-04-27 15:12:07] ERROR (Notificaciones:347) - IOS: Error en envio notificaciones - CommunicationException: javapns.communication.exceptions.CommunicationException: Communication exception: java.net.ConnectException: Expir tiempo de conexiConnection timed out) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:156) at javapns.notification.PushNotificationManager.initializeConnection(PushNotificationManager.java:106) at javapns.notification.transmission.NotificationThread.runList(NotificationThread.java:215) at javapns.notification.transmission.NotificationThread.run(NotificationThread.java:199) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.ConnectException: Expir tiempo de conexiConnection timed out) at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:576) at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:635) at sun.security.ssl.SSLSocketImpl.(SSLSocketImpl.java:423) at sun.security.ssl.SSLSocketFactoryImpl.createSocket(SSLSocketFactoryImpl.java:88) at javapns.communication.ConnectionToAppleServer.getSSLSocket(ConnectionToAppleServer.java:153) ... 4 more

我的代码如下:

private static void realizaEnvioIOSLista (final List<DispositivoDto> dispositivos, final String textoES, final String textoCA, final String textoEN, final String tipoNotificacion){  

     Thread thread = new Thread(){ 
      public void run(){    
       try {   
        final List<String> idsDispositivos = new ArrayList<String>();     

        final String keystore = XmlUtils.dirCertIOS + XmlUtils.nomCertificado; 
        final String password = XmlUtils.password; 
        final boolean production = XmlUtils.production; 

        //Obtenemos los ids de los dispositivos 
        for(DispositivoDto r : dispositivos) 
         idsDispositivos.add(r.getIdDispositivo());     

        PushNotificationPayload payload = PushNotificationBigPayload.complex(); 

        /* Customize the payload */ 
        payload.addAlert(textoES);  
//     payload.addSound('default'); 
        payload.setContentAvailable(true); 

        payload.addCustomDictionary("es", textoES); 
        payload.addCustomDictionary("en", textoCA); 
        payload.addCustomDictionary("ca", textoEN); 
        payload.addCustomDictionary("tiponotificacion", tipoNotificacion); 

        List<PushedNotification> notifications = new ArrayList<PushedNotification>(); 

        if(idsDispositivos.size()<= 200){ 
         notifications = Push.payload(payload, keystore, password, production, idsDispositivos); 

        } else { 
         int threads = 1; 

         if(dispositivos.size() > 200) { 
          threads = (int) Math.ceil(dispositivos.size()/200); 
         } 

         notifications = Push.payload(payload, keystore, password, production, threads, idsDispositivos); 
        } 

        int dispEliminados = 0; 
        int dispNotificados = 0; 

        for (PushedNotification notification : notifications) { 
         if (notification.isSuccessful()) { 
          dispNotificados ++; 
         } else { 
          String invalidToken = notification.getDevice().getToken(); 

          int index = idsDispositivos.indexOf(invalidToken); 

          Integer usuario = dispositivos.get(index).getUsuario(); 
          String idHardware = dispositivos.get(index).getIdHardwareDis(); 

          aBD.unregisterDispositivo(usuario, invalidToken,idHardware); 
          dispEliminados ++; 

     //     Exception theProblem = notification.getException(); 
     //     theProblem.printStackTrace(); 

          //If the problem was an error-response packet returned by Apple, get it 
          ResponsePacket theErrorResponse = notification.getResponse(); 

          if (theErrorResponse != null){ 
           logNot.info("IOS: " +theErrorResponse.getMessage()); 
          } 
         } 
        } 
        logNot.info("IOS: Dispositivos Notificados correctamente: " + dispNotificados); 
        logNot.info("IOS: Dispositivos Eliminados: " +dispEliminados); 

       } catch (CommunicationException e) { 
        logNot.error("IOS: Error en envio notificaciones - CommunicationException: ",e); 
       } catch (KeystoreException e) { 
        logNot.error("IOS: Error en envio notificaciones - KeystoreException: ",e); 
       } catch (JSONException e) { 
        logNot.error("IOS: Error en envio notificaciones - JSONException: ",e); 
       } catch (Exception e) { 
        logNot.error("IOS: Error en envio notificaciones",e); 
       } 
      } 
     }; 

     thread.start(); 
    } 

出问题了吗?苹果服务器的最大设备数量和连接数量是多少?欢迎任何帮助。

回答

0

我发现我的问题的解决方案,代码工作正常,与系统管理员交谈后,我们可以看到,这是一个服务器配置问题,因为根据此链接apple能够发送通知,以下必须考虑:

To use Apple Push Notification service (APNs), your Mac and iOS clients need a direct and persistent connection to Apple's servers.

这样:

If you use Wi-Fi behind a firewall, or private Access Point Name for cellular data, connect to specific ports. You need a direct, unproxied connection to the APNs servers on these ports:

  • TCP port 5223 to communicate with APNs.
  • TCP port 2195 to send notifications to APNs.
  • TCP port 2196 for the APNs feedback service.
  • TCP port 443 is required during device activation, and afterwards for fallback (on Wi-Fi only) if devices can't reach APNs on port 5223.

此外:

The APNs servers use load balancing, so your devices don't always connect to the same public IP address for notifications. It's best to let your device access these ports on the entire 17.0.0.0/8 address block, which is assigned to Apple.

因此,通过由系统管理员配置防火墙来允许这些连接解决了所有问题。我希望它能帮助别人。