我是苍王,如下是我这个系列的相关文章,有兴趣能够参考一下,能够给个喜欢或者关注个人文章。 [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();
}
}
复制代码
读取到是顶部信息架构
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置为falseapp
@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链接和断开时间,适配出最适当的发送长连接时间,有兴趣能够本身实验写一个算法。 微信的智能心跳方案dom
这边作IM的应用的,说一下这边方案,仅供参考。 手机进入后台后十秒后主动关闭长链接,经过推送来维护消息,这里有个问题就是国内的Umeng推送可达率你们懂的,小米和华为还好点,若是是其余山寨机,到8.0后后台很难保活了。若是是国外FCM送达率是很是高的,若是是最推国外平台,直接依靠推送也很是可靠。socket