Apple APNS http2 Provider 開發 使用 okHttp

前言

Apple 升級了後臺推送接口,使用 http2 協議,提升了 payload 的最大大小(4k),本文介紹新版 APNS 實現方法git

基於 okhttp 框架

http2 框架

不要使用 okhttp3 的 Request 類直接發送 post 請求,由於 http3 底層雖然使用了 ConnectionPool,能夠設置 keep alive 和 keep alive duration,可是超過 keep alive duration,連接仍是會斷開,而 Apple 官方建議保持長連接!github

因此最好自建 socket 長連接,使用 okhttp3 底層的 FramedConnection 類來直接發送 http2
請求,並經過定時 PING 幀來保持連接app

在實際開發中,Apple 的 development 環境也很是不穩定,常常 連接超時 和 ssl 握手超時,大多數狀況下只能創建一個連接,第二個鏈接要麼連不上,要麼在 ssl 握手斷開框架

實現

Http2ApnsConnection

Http2ApnsConnection 類負責 ssl socket 連接的創建,心跳包發送以及經過 http2 multiple stream 在一個 frame 中發送多條 push notificationsocket

建立 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<Header> 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...post

總結

相關文章
相關標籤/搜索