Kotlin+Netty Android客户端连接

使用Kotlin+Netty Android客户端连接

由于Kotlin也是新的语言,在2017年中下才和Android完全融合
在这里我只写了Netty客户端连接服务器的部分代码,如果想要更多代码可以下方留言
我这个是实用在真实项目中的代码,由于我自己也遇到了很多问题,所以就想分享出来给大家,谢谢

首先在代码中解决了两个重大问题

  • 1.Netty Client启动的时候需要重连
  • 2.在程序运行中连接断掉需要重连。
其他的都不说了直接上代码

package com.ftrd.flashlight.nettys

import com.ftrd.flashlight.FileKt.DelegatesExt
import com.ftrd.flashlight.FileKt.FinalValue;
import com.ftrd.flashlight.FileKt.LogUtils;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener
import java.util.concurrent.TimeUnit


/**
 * @author: Jeff <[email protected]>
 * @date:  2018-02-05 16:54
 * @description: netty连接类
 * 1.Netty Client启动的时候需要重连
 * 2.在程序运行中连接断掉需要重连。
 * 使用object关键字替代class关键字就可以声明一个单例对象
 */
object NettyConnect {
    //companion静态声类声名对象,相当于static关键
    //companion object { // 自定义委托实现单例,只能修改这个值一次.
    //如果要发送数据直接调用NettyConnect.channel?.writeAndFlush(""); 或着 导包直接使用channel.writeAndFlush("")
    var channel: Channel by DelegatesExt.notNullSingleValue<Channel>();
    /*    NioEventLoopGroup可以理解为一个线程池,内部维护了一组线程,
       每个线程负责处理多个Channel上的事件,而一个Channel只对应于一个线程,这样可以回避多线程下的数据同步问题。*/
    private var eventLoopGroup: NioEventLoopGroup? = null;
    /* Bootstrap是开发netty客户端的基础,通过Bootstrap的connect方法来连接服务器端。该方法返回的也是ChannelFuture,
        通过这个我们可以判断客户端是否连接成功,*/
    private var bootstrap: Bootstrap? = null;
    //使用Thread线程进行异步连接
    private var mThread: Thread? = null;
    //ChannelFuture的作用是用来保存Channel异步操作的结果。
    private var future: ChannelFuture? = null;
    //保存连接成功或着失败
    private var onDestrYN: Boolean = false;
    //   }


    //创建连接方法,如果要调用连接,直接调用此方法即可
    fun reConnect() = try {
        mThread = object : Thread("NettyConnect.reConnect") {
            override fun run() {
                // super.run();
                LogUtils.d("NettyConnect",
                        "正在连接服务器 ipStr=${FinalValue.COMMAND_IP},portInt=${FinalValue.COMMAND_PORT}");
                eventLoopGroup = NioEventLoopGroup();
                bootstrap = Bootstrap()
                bootstrap!!.channel(NioSocketChannel::class.java)
                        .group(eventLoopGroup)
                        .option(ChannelOption.TCP_NODELAY, true)
                        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000 * 10)//设置连接超时时间
                        .option(ChannelOption.SO_KEEPALIVE, true)
                        //.remoteAddress(host, port)
                        .handler(object : ChannelInitializer<SocketChannel>() {
                            @kotlin.jvm.Throws(java.lang.Exception::class)
                            override fun initChannel(ch: SocketChannel) {
                                var pipeline: ChannelPipeline = ch.pipeline();
                                //使用pipeline.addLast()添加,Decoder、Encode和Handler对象
                            }
                        })

                //ChannelFuture的作用是用来保存Channel异步操作的结果。
                //不使用监听
                // val future: ChannelFuture = bootstrap!!.connect(FinalValue.COMMAND_IP,FinalValue.COMMAND_PORT).sync();
                //使用监听,监听是否连接或是断开
                // val future: ChannelFuture = bootstrap!!.connect(FinalValue.COMMAND_IP,FinalValue.COMMAND_PORT);
                //{addListener(GenericFutureListener)}的方式来获得通知,而非await()。使用sync异步执行
                future = bootstrap!!.connect(FinalValue.COMMAND_IP, FinalValue.COMMAND_PORT).sync();
                if (future?.isSuccess!!) {
                    //如果连接成功则保存ChannelFuture到Channel
                    channel = future!!.channel() as Channel
                    //channel = future!!.awaitUninterruptibly().channel()
                    onDestrYN=true;//连接成功
                } else {
                    onDestrYN=false;//连接失败
                   while (onDestrYN){//连接失败一直进行连接,不管是什么原因都进行连接
                       LogUtils.d("NettyConnect", "连接失败再次连接")
                       //断开连接,重新进行连接
                       channel?.disconnect()
                       channel?.close()
                       future!!.channel().eventLoop().schedule(
                               {
                                   //重新开新的线程进行连接
                                   if (future?.isSuccess!!) {
                                       //如果连接成功则保存ChannelFuture到Channel
                                       channel = future!!.channel() as Channel
                                       //channel = future!!.awaitUninterruptibly().channel()
                                       onDestrYN=true;//连接成功
                                   }

                               },
                               2,//2秒重新连接
                               TimeUnit.SECONDS);
                   }
                }

            }
        }
        mThread!!.start();
    } catch (ex: Exception) {
        LogUtils.d("NettyConnect", "连接服务器出现异常Exception=${ex.message}");
        destroy();//出现异常结束资源
    } finally {
        LogUtils.d("NettyConnect", "连接关闭资源释放");
    }

    fun destroy() {
        //结束线程
        mThread?.interrupt();
        mThread?.join();
        mThread = null;
        //ChannelFuture,结束监听
        //future?.removeListener { }
        future = null;
        //结束连接
        channel?.closeFuture();
        channel?.flush();
        channel?.close();
       // channel = null;
        //  Bootstrap
        bootstrap = null;
        //结束线程池
        eventLoopGroup?.shutdownGracefully();
        eventLoopGroup = null;

    }
}

猜你喜欢

转载自blog.csdn.net/jeff_yaojie/article/details/79280816
今日推荐