Netty in Android application development in actual combat series (a) --- build a service and client

Read the article suggests looking back from the beginning of the first chapter

This series of articles

First, a brief look at Netty

  • Official website address: https: //netty.io
  • Jar package to download the official website: https: //netty.io/downloads.html
  • Jar package can also go mvnrepository download: https: //mvnrepository.com/artifact/io.netty/netty-all
  • Introduce direct Shangguan network could not be better
    Here Insert Picture Description
  • Google translates
    Netty是一个异步事件驱动的网络应用程序框架用于快速开发可维护的高性能协议服务器和客户端。
  • Netty is a NIO non-blocking asynchronous application framework, regarding IO, NIO, AIOunderstanding we can find the article and see

Second, create Tcp server

  • Introducednetty-all-4.1.39.Final.jar

  • Add Network Permissions<uses-permission android:name="android.permission.INTERNET" />

  • Creating NettyServer.javaopen tcp service

public class NettyServer {
    private static final String TAG = "NettyServer";

    //端口
    private static final int PORT = 7010;

    /**
     * 启动tcp服务端
     */
    public void startServer() {
        try {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //添加发送数据编码器
                            pipeline.addLast(new ServerEncoder());
                            //添加解码器,对收到的数据进行解码
                            pipeline.addLast(new ServerDecoder());
                            //添加数据处理
                            pipeline.addLast(new ServerHandler());
                        }
                    });
            //服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成
            b.bind(PORT).sync();
            Log.d(TAG, "TCP 服务启动成功 PORT = " + PORT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • ServerEncoder.javaServer sends the data encoder
public class ServerEncoder extends MessageToByteEncoder<Object> {

    private static final String TAG = "ServerEncoder";

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Object data, ByteBuf byteBuf) throws Exception {
        //自己发送过来的东西进行编码
        byteBuf.writeBytes(data.toString().getBytes());
    }
}
  • ServerDecoder.javaDecoder, the data client parses
public class ServerDecoder extends ByteToMessageDecoder {
    private static final String TAG = "ServerDecoder";

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //收到的数据长度
        int length = byteBuf.readableBytes();
        //创建个byteBuf存储数据,进行编辑
        ByteBuf dataBuf = Unpooled.buffer(length);
        //写入收到的数据
        dataBuf.writeBytes(byteBuf);
        //将byteBuf转为数组
        String data = new String(dataBuf.array());
        Log.d(TAG, "收到了客户端发送的数据:" + data);
        //将数据传递给下一个Handler,也就是在NettyServer给ChannelPipeline添加的处理器
        list.add(data);
    }
}
  • ServerHandler.javaData processor
public class ServerHandler extends SimpleChannelInboundHandler<Object> {

    private static final String TAG = "ServerHandler";

    /**
     * 当收到数据的回调
     *
     * @param channelHandlerContext 封装的连接对像
     * @param o
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
        Log.d(TAG, "收到了解码器处理过的数据:" + o.toString());
    }

    /**
     * 有客户端连接过来的回调
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        Log.d(TAG, "有客户端连接过来:" + ctx.toString());
    }

    /**
     * 有客户端断开了连接的回调
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        Log.d(TAG, "有客户端断开了连接:" + ctx.toString());
    }
}
  • Key: setting childHandler(ChannelHandler childHandler), setting a data processor (of ChannelHandler) of the connecting channels
  • The above adds a data decoding processor, a data processor, the client processes the received data, as shown below:

Third, create a client, and create a similar service to end

  • createNettyClient.java
public class NettyClient {
    private static final String TAG = "NettyClient";
    private final int PORT = 7010;
    //连接的服务端ip地址
    private final String IP = "192.168.3.111";
    private static NettyClient nettyClient;
    //与服务端的连接通道
    private Channel channel;
    
    public static NettyClient getInstance() {
        if (nettyClient == null) {
            nettyClient = new NettyClient();
        }
        return nettyClient;
    }
    /**
     *需要在子线程中发起连接
     */
    private NettyClient() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                connect();
            }
        }).start();
    }
    /**
     * 获取与服务端的连接
     */
    public static Channel getChannel() {
        if (nettyClient == null) {
            return null;
        }
        return nettyClient.channel;
    }
    /**
     * 连接服务端
     */
    public void connect() {
        try {
            NioEventLoopGroup group = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap()
                    // 指定channel类型
                    .channel(NioSocketChannel.class)
                    // 指定EventLoopGroup
                    .group(group)
                    // 指定Handler
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //添加发送数据编码器
                            pipeline.addLast(new ClientEncoder());
                            //添加数据处理器
                            pipeline.addLast(new ClientHandler());
                        }
                    });
            // 连接到服务端
            ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(IP, PORT));
            //获取连接通道
            channel = channelFuture.sync().channel();
        } catch (Exception e) {
            Log.e(TAG, "连接失败:" + e.getMessage());
            e.printStackTrace();
        }
    }
}
  • ClientEncoder.javaEncoding of data to be transmitted
public class ClientEncoder extends MessageToByteEncoder<Object> {

    private static final String TAG = "ClientEncoder";

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Object data, ByteBuf byteBuf) throws Exception {
        //自己发送过来的东西进行编码
        byteBuf.writeBytes(data.toString().getBytes());
    }
}
  • ClientHandler.javaData processor
public class ClientHandler extends SimpleChannelInboundHandler<Object> {

    private static final String TAG = "ClientHandler";

    /**
     * 当收到数据的回调
     *
     * @param channelHandlerContext 封装的连接对像
     * @param o
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {

    }

    /**
     * 与服务端连接成功的回调
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        Log.d(TAG, "与服务端连接成功:" + ctx.toString());
    }

    /**
     * 与服务端断开的回调
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        Log.d(TAG, "与服务端断开连接:" + ctx.toString());
    }
}

Fourth, start the server first start the client, so that you can establish a connection

  • Start the server
 NettyServer server = new NettyServer();
 server.startServer();
  • Start the client
NettyClient client = NettyClient.getInstance();
  • running result
    Here Insert Picture Description
    Here Insert Picture Description

V. The next article focuses on Encoder, Decoderand Handlerexplain explanation

Demo will be given in the fourth article in this series

Published 140 original articles · won praise 546 · views 540 000 +

Guess you like

Origin blog.csdn.net/a_zhon/article/details/100569489