美文网首页netty
netty echo 入门实现及启动完整介绍

netty echo 入门实现及启动完整介绍

作者: 黎明_dba5 | 来源:发表于2020-01-18 10:47 被阅读0次

    说明

    避免走弯路,查找各种资料,本文提供完整的NettyServer及NettyClient的完整实现,及启动,方便其他初学者参考,不对代码本身做解说。

    NettyServer

    新建一个maven空白项目,项目名NettyServer

    根pom.xml文件中加入netty依赖

    <dependencies>
           <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
           <dependency>
               <groupId>io.netty</groupId>
               <artifactId>netty-all</artifactId>
               <version>4.1.44.Final</version>
           </dependency>
       </dependencies>
    
    创建EchoServerHandler,具体实现
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.*;
    import io.netty.util.CharsetUtil;
    
    /**
     * 
     */
    //标示一个ChannelHandler可以被多个channel安全的共享
    @ChannelHandler.Sharable
    public class EchoServerHandler extends ChannelInboundHandlerAdapter{
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            ByteBuf in =(ByteBuf)msg;
            //将消息记录到控制台
            System.out.println("Server received:" + in.toString(CharsetUtil.UTF_8));
            //将接受到的消息写给发送者,而不冲刷出站消息
            ctx.write(in);
        }
    
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            //将未决消息冲刷到远程节点,并且关闭改Channel
            ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            //打印异常栈信息
            cause.printStackTrace();
            //关闭该Channel
            ctx.close();
        }
    }
    
    
    创建启动引导类
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    import java.net.InetSocketAddress;
    
    /**
     *
     */
    public class EchoServer {
        private final int port;
        public EchoServer(int port){
            this.port = port;
        }
    
        public static void main(String[] args) throws Exception {
            if (args.length != 1){
                System.err.println("Usage:" + EchoServer.class.getSimpleName() + "<port>");
            }
            int port = Integer.parseInt(args[0]);
            System.out.println(port);
            new EchoServer(port).start();
        }
    
        public void start() throws Exception{
            final EchoServerHandler serverHandler = new EchoServerHandler();
            EventLoopGroup group = new NioEventLoopGroup();
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.group(group)
                        .channel(NioServerSocketChannel.class)
                        .localAddress(new InetSocketAddress(port))
                        //添加一个EchoServerHandler到子Channel的ChannelPipeline
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel socketChannel) throws Exception {
                                socketChannel.pipeline().addLast(serverHandler);
                            }
                        });
                //异步的绑定服务器,调用sync()方法阻塞等待直到绑定完成
                ChannelFuture channelFuture = bootstrap.bind().sync();
                //获取Channel的CloseFuture,并且阻塞当前线程知道它完成
                channelFuture.channel().closeFuture().sync();
            }finally {
                //关闭EventLoopGroup,释放所有的资源
                group.shutdownGracefully().sync();
            }
        }
    }
    
    
    项目配置

    pom.xml文件加入maven插件

    <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.6.0</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <!-- main方法的入口类及参数 -->
                        <mainClass>EchoServer</mainClass>
                        <arguments>
                            <argument>8080</argument>
                        </arguments>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    

    至此,NettyServer项目已经创建完成,接下来创建NettyClient客户端

    NettyClient

    创建一个空白maven项目,项目名NettyClient

    根pom.xml文件中加入netty依赖

    <dependencies>
           <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
           <dependency>
               <groupId>io.netty</groupId>
               <artifactId>netty-all</artifactId>
               <version>4.1.44.Final</version>
           </dependency>
       </dependencies>
    
    EchoClientHandler
    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandler;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    import io.netty.util.CharsetUtil;
    
    /**
     * Created  on 2020/1/16.
     */
    //标记改类的实例可以被多个Channel共享
    @ChannelHandler.Sharable
    public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
    
        //当被通知Channel是活跃的时候,发送一条消息
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
        }
    
        //记录已接受消息的转储
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
            System.out.println("Client received:" + byteBuf.toString(CharsetUtil.UTF_8));
        }
    
        //在发生异常时,记录错误并关闭Channel
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
        }
    }
    
    EchoClient
    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    
    import java.net.InetSocketAddress;
    
    /**
     * Created by lunfu.chen on 2020/1/16.
     */
    public class EchoClient {
        private final String host;
        private final int port;
    
        public EchoClient(String host, int port) {
            this.host = host;
            this.port = port;
        }
    
        public static void main(String[] args) throws Exception {
            System.out.println(">>>>>>>args:"+args[0]+","+args[1]);
            if (args.length != 2) {
                System.err.println("Usage:" + EchoClient.class.getSimpleName() + "<host> <port>");
                return;
            }
            String host = args[0];
            int port = Integer.parseInt(args[1]);
            new EchoClient(host, port).start();
        }
    
        public void start() throws Exception {
            EventLoopGroup group = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                        .channel(NioSocketChannel.class)
                        .remoteAddress(new InetSocketAddress(host, port))
                        .handler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel socketChannel) throws Exception {
                                socketChannel.pipeline().addLast(new EchoClientHandler());
                            }
                        });
                //连接到远程节点,阻塞等待知道连接完成
                ChannelFuture future = b.connect().sync();
                //阻塞,知道Channel关闭
                future.channel().closeFuture().sync();
            } finally {
                //关闭线程池并且释放所有的资源
                group.shutdownGracefully().sync();
            }
        }
    }
    
    
    pom.xml文件中加入manve插件
    <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.6.0</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <!-- 此处为启动类的入口及参数 -->
                        <mainClass>EchoClient</mainClass>
                        <arguments>
                            <argument>localhost</argument>
                            <argument>8080</argument>
                        </arguments>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    

    打包启动项目

    编译和启动项目我提供有两种方式,本质是一样。

    使用idea

    本人使用的编译器是idea,因此在两个项目的Terminal窗口中输入命令
    首先在NettyServer项目中操作,

    mvn clean package
    

    然后会有输出

    D:\workspace_lean\netty\nettyserver>mvn clean package
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building nettyserver 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ nettyserver ---
    [INFO] Deleting D:\workspace_lean\netty\nettyserver\target
    [INFO]
    [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ nettyserver ---
    [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
    [INFO] Copying 0 resource
    [INFO]
    [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ nettyserver ---
    [INFO] Changes detected - recompiling the module!
    [WARNING] File encoding has not been set, using platform encoding GBK, i.e. build is platform dependent!
    [INFO] Compiling 2 source files to D:\workspace_lean\netty\nettyserver\target\classes
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServerHandler.java:[9,7] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServerHandler.java:[9,44] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServerHandler.java:[15,24] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServerHandler.java:[17,28] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServerHandler.java:[29,21] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServer.java:[37,27] 编码GBK的不可映射字符
    [WARNING] /D:/workspace_lean/netty/nettyserver/src/main/java/EchoServer.java:[49,37] 编码GBK的不可映射字符
    [INFO]
    [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ nettyserver ---
    [WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
    [INFO] skip non existing resourceDirectory D:\workspace_lean\netty\nettyserver\src\test\resources
    [INFO]
    [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ nettyserver ---
    [INFO] Nothing to compile - all classes are up to date
    [INFO]
    [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ nettyserver ---
    [INFO] No tests to run.
    [INFO]
    [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ nettyserver ---
    [INFO] Building jar: D:\workspace_lean\netty\nettyserver\target\nettyserver-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 2.099 s
    [INFO] Finished at: 2020-01-18T10:26:24+08:00
    [INFO] Final Memory: 18M/215M
    [INFO] ------------------------------------------------------------------------
    
    

    编译打包成功,然后在Terminal窗口中输入启动命令

    mvn exec:java
    

    随即控制台输出响应信息

    D:\workspace_lean\netty\nettyserver>mvn exec:java
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building nettyserver 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ nettyserver ---
    8080
    
    

    接着在NettyClient项目中执行上面两个相同的命令,最后在NettyServe项目控制台会输出

    Server received:Netty rocks!
    

    在NettyClient项目控制台会输出,并且NettyClient项目随即关闭

    D:\workspace_lean\netty\nettyclient>mvn exec:java
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building nettyclient 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ nettyclient ---
    >>>>>>>args:localhost,8080
    Client received:Netty rocks!
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 6.536 s
    [INFO] Finished at: 2020-01-18T10:32:07+08:00
    [INFO] Final Memory: 8M/190M
    [INFO] -------------------------------
    

    到此,idea实现Netty Echo应用程序已实现完毕,接着介绍使用windows系统命令窗口编译和启动这一功能。

    使用CMD命令窗口

    打开命令窗口,进入各自的项目文件处,eg


    image.png

    项目路径为


    image.png

    进入项目位置后,依次执行mvn clean package和mvn exec:java

    image.png image.png

    到此步,NettyServer已经启动成功,同样的方式启动NettyClient,

    并且可以使用命令窗口启动多个client客户端

    可以使用Ctrl+C关闭客户端,或者简单粗暴直接关闭idea或者命令窗口,使用命令关闭窗口方式示列


    image.png

    第一款Netty应用程序实现及启动介绍完毕!

    相关文章

      网友评论

        本文标题:netty echo 入门实现及启动完整介绍

        本文链接:https://www.haomeiwen.com/subject/twkkzctx.html