热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AppleAPNShttp2Provider开发使用okHttp

前言Apple升级了后台推送接口,使用http2协议,提高了payload的最大大小(4k),本文介绍新版APNS实现方法基于okhttp框架http2框架不要使用okhttp3的
前言

Apple 升级了后台推送接口,使用 http2 协议,提高了 payload 的最大大小(4k),本文介绍新版 APNS 实现方法

基于 okhttp 框架

http2 框架

不要使用 okhttp3 的 Request 类直接发送 post 请求,因为 http3 底层虽然使用了 ConnectionPool,可以设置 keep alive 和 keep alive duration,但是超过 keep alive duration,链接还是会断开,而 Apple 官方建议保持长链接!

所以最好自建 socket 长链接,使用 okhttp3 底层的 FramedConnection 类来直接发送 http2
请求,并通过定时 PING 帧来保持链接

在实际开发中,Apple 的 development 环境也非常不稳定,经常 链接超时 和 ssl 握手超时,大多数情况下只能建立一个链接,第二个连接要么连不上,要么在 ssl 握手断开

实现

Http2ApnsConnection

Http2ApnsConnection 类负责 ssl socket 链接的建立,心跳包发送以及通过 http2 multiple stream 在一个 frame 中发送多条 push notification

创建 ssl socket

private Socket createSocket() throws IOException {
debug("connect socket");
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port));
debug("socket connected");
SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(
socket, host, port, true);
sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
sslSocket.setKeepAlive(true);
debug("start ssl handshake");
sslSocket.startHandshake();
debug("handshake success");
return sslSocket;
}

创建 frame connection

private void createFramedConnection() throws IOException {
debug("createFramedConnection");
Socket socket = createSocket();
framedCOnnection= new FramedConnection.Builder(true)
.socket(socket)
.protocol(Protocol.HTTP_2)
.listener(this)
.build();
framedConnection.sendConnectionPreface();
framedCOnnectionAlive= true;
pingFuture = pingService.scheduleAtFixedRate(new PingTask(), 0, PING_PERIOD, TimeUnit.SECONDS);
}

发送 http2 header

private void sendHeader(String token, int contentLength) throws IOException {
// 创建 http2 header,参考 apple apns 开发文档
List headers = Arrays.asList(METHOD_POST_HEADER,
SCHEME_HEADER,
USER_AGENT_HEADER,
CONTENT_TYPE_HEADER,
new Header(":path", "/3/device/" + token),
new Header("authority", host),
new Header("content-length", String.valueOf(contentLength)));
// 创建 stream
framedStream = framedConnection.newStream(headers, true, true);
framedStream.readTimeout().timeout(timeOut, TimeUnit.MILLISECONDS);
framedStream.writeTimeout().timeout(timeOut, TimeUnit.MILLISECONDS);
}

发送 http2 data

private void sendData(byte[] bytes) throws IOException {
Buffer buffer = new Buffer();
buffer.write(bytes);
framedStream.getSink().write(buffer, bytes.length);
framedStream.getSink().flush();
}

Http2ApnsConnectionPool

Http2ApnsService

基于 netty 框架

整体代码结构和 基于 okhttp 框架的差不多,可以参考 https://github.com/black-bamb…

总结
推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • Win10 64位旗舰版的优势及特点详解
    本文详细介绍了Win10 64位旗舰版的优势及特点,包括更安全的源安装盘、永久激活方式、稳定性和硬件驱动的集成,以及人性化的维护工具和分区功能。通过阅读本文,您将了解到Win10 64位旗舰版相比其他版本的优势和特点。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • SpringBoot简单日志配置
     在生产环境中,只打印error级别的错误,在测试环境中,可以调成debugapplication.properties文件##默认使用logbacklogging.level.r ... [详细]
author-avatar
就是-chen
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有