SocketException:推送到生产目的地时远程主机关闭连接

SocketException: Connection closed by remote host when pushing to producation destination

我需要向 IOS 台设备发送通知,我们使用 Java 作为后端。 我正在使用 notnoop/java-apns 库将通知推送到 IOS 台设备。

当我尝试使用生产证书和生产目的地推送到 APNS 时,出现 SocketException:Connection closed by remote host

service = APNS.newService()
            .withCert(classLoader.getResourceAsStream("files/Production_Certificate.p12"), "password")
            .withDelegate(delegate)
            .withProductionDestination()
            .build();

当我使用开发证书和沙箱目标时,一切正常,设备收到推送通知。

我尝试使用其他工具和我们的生产证书推送通知,并且已收到推送,因此证书有效。 我不明白出了什么问题。我做错了什么,或者是一些网络相关的问题,还是图书馆出了什么问题?

以下是堆栈跟踪:-

Couldn't send message after 3 retries.Message(Id=1; Token=0557A5BE7EEA5718A1064FC138EEE855BBDDE15FC8C5841CEADBAD2716A42AEC; Payload={"aps":{"alert":{"body":"Tasks have been assigned to you.","title":"New tasks!"},"sound":"default","badge":1}}) java.net.SocketException: Connection closed by remote host at sun.security.ssl.SSLSocketImpl.checkWrite(SSLSocketImpl.java:1490) at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123) at java.io.OutputStream.write(OutputStream.java:75) at com.notnoop.apns.internal.ApnsConnectionImpl.sendMessage(ApnsConnectionImpl.java:328) at com.notnoop.apns.internal.ApnsConnectionImpl.sendMessage(ApnsConnectionImpl.java:312) at com.notnoop.apns.internal.ApnsServiceImpl.push(ApnsServiceImpl.java:46) at com.notnoop.apns.internal.AbstractApnsService.push(AbstractApnsService.java:89) at com.notnoop.apns.internal.ApnsServiceImpl.push(ApnsServiceImpl.java:36) at com.mobileinsight.api.service.impl.IOSBroadcastServiceImpl.broadcastNewTaskNotifications(IOSBroadcastServiceImpl.java:125) at com.mobileinsight.api.service.impl.IOSBroadcastServiceImpl.broadcastIOSPushNotifications(IOSBroadcastServiceImpl.java:60) at com.mobileinsight.api.service.impl.PushNotificationServiceImpl.pushNotificationsInBulk(PushNotificationServiceImpl.java:29) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at com.sun.proxy.$Proxy136.pushNotificationsInBulk(Unknown Source) at com.mobileinsight.api.quartz.PushNotificationBatchRunner.doWork(PushNotificationBatchRunner.java:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:178) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745)

检查您是否使用了网络代理。尝试 ping 目标 IP 地址。

终于找到问题了。此库接受的 p12 文件应仅包含一个证书,在本例中为生产证书。

我们一直使用的密钥库文件包含多个证书。 java 库对选择哪个库感到困惑。 Java 的 SSL 系统自动使用文件中的第一个证书,因此显然一个服务器或另一个服务器将永远无法工作,具体取决于文件中证书的顺序。

为了解决这个问题,我们为每个生成了不同的密钥库文件。所以我们只从钥匙串中导出(以 .p12 格式)生产证书。

如果 p12 文件只包含一个证书,即使是强硬的库也能正常工作。