写在前面
贴个Kula高清图镇楼:
在之前的跟我一起开发商业级IM(1)—— 技术选型及协议定义和跟我一起开发商业级IM(2)—— 接口定义及封装两篇文章,我们已经了解IMS的技术选型及接口定义与封装,接下来,我们来真正实现连接及重连部分。
一个社交产品,长连接稳定是前提,绝大部分业务逻辑的正常运行都需要稳定的长连接支撑,可谓重中之重。本篇文章将会讲述如何去实现并维护一个稳定的长连接,以及各种异常情况的处理等。阅读完本篇文章,你将会学到连接、重连机制、心跳机制等知识。同时,会在Github上开源相关代码(包含Android客户端/Java服务端、基于TCP/WebSocket),废话不说,我们开始吧。
初始化配置
初始化配置,也就是在应用程序启动并进行IMS
初始化时,传入所需配置参数,可根据自己的业务需求自定义。下面我们来看看NettyTCPIMS
初始化接口的代码实现(由于基于Netty
和WebSocket
实现的NettyWebSocketIMS
大部分代码及逻辑都与NettyTCPIMS
相同,就不单独贴出NettyWebSocketIMS
代码了,下面只会讲解WebSocket
对比TCP
实现所不同的地方,有需要完整代码的话可以跳转Github查看):
/**
* 初始化
* @param context
* @param options IMS初始化配置
* @param connectStatusListener IMS连接状态监听
* @param msgReceivedListener IMS消息接收监听
* @return
*/
@Override
public boolean init(Context context, IMSOptions options, IMSConnectStatusListener connectStatusListener, IMSMsgReceivedListener msgReceivedListener) {
if (context == null) {
Log.d(TAG, "初始化失败:Context is null.");
initialized = false;
return false;
}
if (options == null) {
Log.d(TAG, "初始化失败:IMSOptions is null.");
initialized = false;
return false;
}
this.mContext = context;
this.mIMSOptions = options;
this.mIMSConnectStatusListener = connectStatusListener;
this.mIMSMsgReceivedListener = msgReceivedListener;
executors = new ExecutorServiceFactory();
// 初始化重连线程池
executors.initBossLoopGroup();
// 注册网络连接状态监听
NetworkManager.getInstance().registerObserver(context, this);
// 标识ims初始化成功
initialized = true;
// 标识ims已打开
isClosed = false;
callbackIMSConnectStatus(IMSConnectStatus.Unconnected);
return true;
}
如上图,简单讲讲初始化的几个步骤:
- 参数
- context
应用程序上下文,方便IMS获取系统资源并进行一些系统操作等。 - options
IMS初始化所需配置,其中定义了通信实现方式、通信协议、传输协议、连接超时时间、重连延时时间、重连次数、心跳前后台间隔时间、服务器地址等一些支持自定义的参数。 - connectStatusListener
IMS连接状态回调,便于把连接状态反馈到应用层。 - msgReceivedListener
消息接收回调,便于IMS把接收到的消息回调到应用层(本篇文章主要讲解连接及重连,所以不涉及消息部分,后续会详细讲解)。
- 创建线程池组
线程池组分为boss线程池和work线程池,其中boss线程池负责连接及重连部分;work线程池负责心跳部分,均为单线程线程池(因为同时只能有一个线程进行连接或心跳)。至于为什么用线程池,纯属个人习惯,大家也可以分别用一个子线程实现即可。 - 注册网络状态监听
网络变化时,进行IMS重连。
初始Bootstrap
初始化Bootstrap,可参考Netty Channel