Android tcp,udp,netty 记录

tcp,udp,netty 记录

udp发送广播:

获取本机wifi ip地址,最后一位改为255,发送全c网段广播

private fun getWIFIIp() : InetAddress{
    val toString = NetworkUtils.getIpAddressByWifi().toString()
    val lastIndexOf = toString.lastIndexOf(".")
    val substring = toString.substring(0,lastIndexOf+1)
    return InetAddress.getByName(substring+"255")
}

创建DatagramSocket对象,发送广播或点对点发送消息,端口号:15001

@Synchronized fun sendDataMsg(host : InetAddress = getWIFIIp() ,msg : String){
    try {
        val datagramSocket = DatagramSocket()
        datagramSocket.broadcast = true
        val datagramPacket = DatagramPacket(msg.toByteArray(),msg.toByteArray().size, host, 15001)
        datagramSocket.send(datagramPacket)
        LogUtils.i(msg)
        datagramSocket.close()
    }catch (e : Exception){
        ToastUtils.showShort("udp 发送失败")
    }
}

接收指定端口号的消息:

@Synchronized fun receiveDataMsg(port: Int,listener: Listener){
    diskIO.execute {
        var datagramSocket : DatagramSocket? = null
        try {
            val byteArray = ByteArray(1024)

// val byName = InetAddress.getByName(NetworkUtils.getIpAddressByWifi())
datagramSocket = DatagramSocket(port)
datagramSocket.broadcast = true
val datagramPacket = DatagramPacket(byteArray, byteArray.size)
while (isReceive){
datagramSocket.receive(datagramPacket)
val data = String(datagramPacket.data, 0, datagramPacket.length)
LogUtils.i(“udp read data ::$data”,datagramPacket.address,datagramPacket.length)
val indexOf = data.indexOf("{")
listener.onReceive(data.substring(indexOf, data.length))
}
}catch (e : Exception){
e.printStackTrace()
ToastUtils.showShort(“udp 接收异常”)
}finally {
datagramSocket?.close()
}
}
}

发送组播,ip地址指定为:224.0.0.1

val byteArray = msg.toByteArray()
val multicastSocket = MulticastSocket()
multicastSocket.timeToLive = 1
val byName = InetAddress.getByName("224.0.0.1")
multicastSocket.joinGroup(byName)
 val datagramPacket = DatagramPacket(byteArray,0,byteArray.size,byName,port)
 multicastSocket.send(datagramPacket)
 multicastSocket.close()

接收组播:

val byteArray = ByteArray(1024)
        val byName = InetAddress.getByName("224.0.0.1")
        val multicastSocket = MulticastSocket(port)
        multicastSocket.timeToLive = 1
        multicastSocket.joinGroup(byName)
        val datagramPacket = DatagramPacket(byteArray, byteArray.size)
        multicastSocket.receive(datagramPacket)
tcp socket链接:

初始化socket对象:

mRunFlag = true;
      try {
        mSocket = new Socket(mHost, mPort);
        mInputStream = new DataInputStream(mSocket.getInputStream());
        mOutputStream = new DataOutputStream(mSocket.getOutputStream());
      } catch (IOException e) {
        e.printStackTrace();
        mRunFlag = false;
      }
      if (mRunFlag) {
        //连接成功开启一个新的线程读取数据
        mReadThread = new ReadThread();
        mReadThread.start();
      }

开启读线程,循环读取消息:

try {
          String text = mInputStream.readLine();
          Log.d(TAG, "read: " + text);
          //如果收到null数据表示连接出错,使用break退出循环
          if (text == null) {
            mRunFlag = false;
            break;
          }
          notifyReceive(text);
        } catch (IOException e) {
          mRunFlag = false;
          e.printStackTrace();
        }
      }

用outputstream发送消息

if (mOutputStream != null && text != null) {
      try {
        mOutputStream.write(text.getBytes());
        mOutputStream.flush();
        return true;
      } catch (IOException e) {
        mRunFlag = false;
        e.printStackTrace();
      }
    }
netty使用:

build.gradle里添加依赖:

implementation 'io.netty:netty-all:4.0.47.Final'

初始化 nio,设置编码,解码器等:

nioEventLoopGroup = NioEventLoopGroup()
        bootstrap = Bootstrap()
        bootstrap?.group(nioEventLoopGroup)
            ?.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,3000)  //超时时间
            ?.channel(NioSocketChannel::class.java)
            ?.handler(object : ChannelInitializer<SocketChannel>() {
                override fun initChannel(ch: SocketChannel?) {
                    ch?.pipeline()?.addLast(object : MessageToByteEncoder<String>() {  //自定义 编码器
                        override fun encode(ctx: ChannelHandlerContext?, msg: String?, out: ByteBuf?) {
                            out?.writeBytes(msg?.toByteArray())
                        }
                    })
                        ?.addLast(IdleStateHandler(0,0,20))  //读取空闲,写入空闲,所有空闲
//                        ?.addLast(FixedLengthFrameDecoder(1024))  //固定长度  解码器
//                        ?.addLast(DelimiterBasedFrameDecoder(1024,delimiter)) //限定符  解码器
//                        ?.addLast(LengthFieldBasedFrameDecoder(1024_00,0,4,0,12))  //指定长度  解码器
//                        ?.addLast(TcpDecode())  //自定义解码器
                        ?.addLast(HandlerAdapter())  //读取消息handler
                }
            })

tcp连接,host:IP地址,port:端口号

try {
            bootstrap?.connect(mHost, mPort)?.addListener {  //异步连接
                if (it.isSuccess){  //连接成功
                    LogUtils.i("connect $mHost")
                    ch = (it as ChannelFuture).channel()   //拿到 通道,通过 channel 发送消息
                    isStop = false
                    mListener?.connectSuccess(mHost,mPort)   //连接成功回调
                }else{
                    (it as ChannelFuture).channel().eventLoop().schedule({   //连接失败
                        stopConnect()
                        connect(mHost,mPort)
                    },2,TimeUnit.SECONDS)   //2s 后重连
                }
            }?.sync()
        }catch (e: Exception){
            e.printStackTrace()
        }

断开连接:

if (ch != null && ch!!.isOpen){  //断开连接
            ch?.close()
            ch = null
        }
        if (nioEventLoopGroup != null){
            nioEventLoopGroup?.shutdownGracefully()
            nioEventLoopGroup = null
        }

通过 channel 发送消息

if (ch != null && ch!!.isOpen){
            ch?.writeAndFlush("$s")?.addListener {
                if (!it.isSuccess){   //发送失败
                    mListener?.writeFail(s)
                }
            }
        }

读取消息,心跳包发送:

inner class HandlerAdapter : ChannelInboundHandlerAdapter(){
        override fun channelRead(ctx: ChannelHandlerContext?, msg: Any?) {   //未定义解码器,所以msg 为 bytebuf
            val str = if (msg is ByteBuf) bytebufToString(msg) else ""
            LogUtils.i(str)
            mListener?.resultMsg(mHost,mPort,str)
        }

        override fun exceptionCaught(ctx: ChannelHandlerContext?, cause: Throwable?) {
            cause?.printStackTrace()
            ctx?.close()
        }

        @Synchronized fun bytebufToString(buf : ByteBuf) : String{
            var str = ""
            if(buf.hasArray()) { // 处理堆缓冲区
                str = String(buf.array(), buf.arrayOffset() + buf.readerIndex(), buf.readableBytes())
            } else { // 处理直接缓冲区以及复合缓冲区
                val bytes = ByteArray(buf.readableBytes())
                buf.getBytes(buf.readerIndex(), bytes)
                str =String(bytes, 0, buf.readableBytes())
            }
            return str
        }

        override fun userEventTriggered(ctx: ChannelHandlerContext?, evt: Any?) {
            if (evt is IdleStateEvent) {
                when (evt.state()) {
                    IdleState.ALL_IDLE -> {  // 前面设置 20ms 没有读取,发送消息,为所有空闲状态,发送心跳包
                        val baseReponseBean = BaseReponseBean(30, 1, Heart(mPwd), gatewayid = 12345678)
                        writeData(baseReponseBean.toString())
                    }
                }
            }else{
                super.userEventTriggered(ctx, evt)
            }
        }

        override fun channelInactive(ctx: ChannelHandlerContext?) {  // tcp 断开连接
            super.channelInactive(ctx)
            ctx?.channel()?.eventLoop()?.schedule({
                LogUtils.i("channel in active and reset connect")
                stopConnect()
                connect(mHost,mPort,mPwd)
            },2,TimeUnit.SECONDS)  //2s 后 重连
            ctx?.close()
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值