我是苍王,如下是我这个系列的相关文章,有兴趣能够参考一下,能够给个喜欢或者关注个人文章。 [Android]如何作一个崩溃率少于千分之三噶应用app--章节列表web
这一张很是经典的心跳策略图示 算法
如今通常的心跳策略,都是从客户端发送一个ping信号给服务器,告诉服务器是长链接存活。 服务器会返回一个pong信号给客户端,让其更新心跳线程时间。若是超时没有接收到信号,那么客户端考虑重连机制。bash
这里说一下okhttp有提供了WebSocket的封装,咱们的应用也是使用了WebSocket,那就直接看一下WebSocket对pingpong的封装服务器
public Builder() { …… //这里默认的ping的时间间隔为0,由于okhttp也能够有如http短链接 pingInterval = 0; } Builder(OkHttpClient okHttpClient) { …… //builder函数提供封装 this.pingInterval = okHttpClient.pingInterval; } //设置间隔 public Builder pingInterval(long interval, TimeUnit unit) { pingInterval = checkDuration("interval", interval, unit); return this; } 复制代码
在RealWebSocket中启动循环发送ping信号微信
public void initReaderAndWriter(String name, Streams streams) throws IOException { synchronized (this) { this.streams = streams; this.writer = new WebSocketWriter(streams.client, streams.sink, random); this.executor = new ScheduledThreadPoolExecutor(1, Util.threadFactory(name, false)); if (pingIntervalMillis != 0) { //循环定时任务 executor.scheduleAtFixedRate( new PingRunnable(), pingIntervalMillis, pingIntervalMillis, MILLISECONDS); } if (!messageAndCloseQueue.isEmpty()) { runWriter(); // Send messages that were enqueued before we were connected. } } reader = new WebSocketReader(streams.client, streams.source, this); } private final class PingRunnable implements Runnable { PingRunnable() { } @Override public void run() { //写入ping信号 writePingFrame(); } } void writePingFrame() { WebSocketWriter writer; int failedPing; synchronized (this) { if (failed) return; writer = this.writer; //是否等待pong信号 failedPing = awaitingPong ? sentPingCount : -1; //等待ping计数 sentPingCount++; //等待pong awaitingPong = true; } //ping失败,长链接失效 if (failedPing != -1) { failWebSocket(new SocketTimeoutException("sent ping but didn't receive pong within " + pingIntervalMillis + "ms (after " + (failedPing - 1) + " successful ping/pongs)"), null); return; } try { //写入空支付到websocket头部 writer.writePing(ByteString.EMPTY); } catch (IOException e) { failWebSocket(e, null); } } 复制代码
在RealWebSocket的call中执行loopReader监听读取接收到的信息websocket
/** Receive frames until there are no more. Invoked only by the reader thread. */ public void loopReader() throws IOException { //监听信息 while (receivedCloseCode == -1) { // This method call results in one or more onRead* methods being called on this thread. reader.processNextFrame(); } } void processNextFrame() throws IOException { //读取头部 readHeader(); if (isControlFrame) { //读取头部信息体 readControlFrame(); } else { readMessageFrame(); } } 复制代码
读取到是顶部信息markdown
private void readControlFrame() throws IOException { if (frameLength > 0) { source.readFully(controlFrameBuffer, frameLength); if (!isClient) { controlFrameBuffer.readAndWriteUnsafe(maskCursor); maskCursor.seek(0); toggleMask(maskCursor, maskKey); maskCursor.close(); } } switch (opcode) { //读取ping信号 case OPCODE_CONTROL_PING: frameCallback.onReadPing(controlFrameBuffer.readByteString()); break; //读取pong信号 case OPCODE_CONTROL_PONG: frameCallback.onReadPong(controlFrameBuffer.readByteString()); break; //读取到关闭链接信号 case OPCODE_CONTROL_CLOSE: int code = CLOSE_NO_STATUS_CODE; String reason = ""; long bufferSize = controlFrameBuffer.size(); if (bufferSize == 1) { throw new ProtocolException("Malformed close payload length of 1."); } else if (bufferSize != 0) { code = controlFrameBuffer.readShort(); reason = controlFrameBuffer.readUtf8(); String codeExceptionMessage = WebSocketProtocol.closeCodeExceptionMessage(code); if (codeExceptionMessage != null) throw new ProtocolException(codeExceptionMessage); } frameCallback.onReadClose(code, reason); closed = true; break; default: throw new ProtocolException("Unknown control opcode: " + toHexString(opcode)); } } 复制代码
读取到pong信号,等待pong置为false架构
@Override public synchronized void onReadPong(ByteString buffer) { // This API doesn't expose pings. receivedPongCount++; awaitingPong = false; } 复制代码
这就是使用OkHttp的WebSocket keepAlive的流程,而基本的okhttp的socket链接也是经过相似发送这种pingpong信号来维持,之须要设置维护的时间。 而后keepAlive的经验之前的经验值是59秒,微信的大神的方案是经过记录socket链接和断开时间,适配出最适当的发送长连接时间,有兴趣能够本身实验写一个算法。 微信的智能心跳方案app
这边作IM的应用的,说一下这边方案,仅供参考。 手机进入后台后十秒后主动关闭长链接,经过推送来维护消息,这里有个问题就是国内的Umeng推送可达率你们懂的,小米和华为还好点,若是是其余山寨机,到8.0后后台很难保活了。若是是国外FCM送达率是很是高的,若是是最推国外平台,直接依靠推送也很是可靠。dom