关于Netty的一点初步认识

关于Netty的一点初步认识

最初接触

刚开始接触Netty时,搜索相关资料及教程,就看到了关于 Netty5 的一些教程
打开Netty官网,却没有找到关于Netty5的影子,只感觉了有点奇怪。

Netty官方对应Githubreleases上,最新的更新也只是关于4.x的版本;
后来在mvnrepository上看到了关于netty5的影子,更新时间为2015年3月,后来在github releases中找到了netty5的版本,不过只更新到netty-5.0.0.Alpha2版本就再也没有更新过;

Netty3 与 Netty4

后来进行了一些简单的对比,总结了一些简单的区别:

  • 3.0.0.CR1 ~ 3.2.10.Final

maven依赖

<!-- https://mvnrepository.com/artifact/org.jboss.netty/netty -->
<!-- 3.0.0.CR1 ~ 3.2.10.Final -->
<dependency>
    <groupId>org.jboss.netty</groupId>
    <artifactId>netty</artifactId>
    <version>3.2.10.Final</version>
</dependency>

包名以org.jboss.netty开头;

  • 3.3.0.Final ~ 3.10.6.Final

maven依赖

<!-- https://mvnrepository.com/artifact/io.netty/netty -->
<!-- 3.3.0.Final ~ 3.10.6.Final -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty</artifactId>
    <version>3.10.6.Final</version>
    <!--<version>3.3.0.Final</version>-->
</dependency>

包名也是以org.jboss.netty开头,只是maven依赖的groupId名发生一些改变;

  • 4.0.0.Final ~ 4.1.35.Final

maven依赖

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<!-- 4.0.0.Final ~ 4.1.35.Final ~ 5.0.0.Alpha2 -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.35.Final</version>
    <!--<version>5.0.0.Alpha2</version>-->
</dependency>

包名改变为以io.netty开头,maven依赖的artifactId名发生一点改变;

Netty3 的一些简单实践

服务端

NettyServer.java

package morning.cat.netty3.x;

import morning.cat.netty3.x.handle.HelloHandle;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @describe: Netty3.x Server
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class NettyServer {

    public static void main(String[] args) {

        // 服务端
        ServerBootstrap bootstrap = new ServerBootstrap();

        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService work = Executors.newCachedThreadPool();

        // 设置 ChannelFactory 工厂
        bootstrap.setFactory(new NioServerSocketChannelFactory(boss, work));

        // 设置 ChannelPipelineFactory 工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {

                // 生成管道
                ChannelPipeline channelPipeline = Channels.pipeline();

                // 接收信息转换成字符串(上行)
                // channelPipeline.addLast("StringDecoder",new StringDecoder());
                // 回写直接写入字符串
                // channelPipeline.addLast("StringEncoder",new StringEncoder());
                channelPipeline.addLast("HelloHandle", new HelloHandle());
                return channelPipeline;
            }
        });

        // 绑定端口
        bootstrap.bind(new InetSocketAddress(59999));
        // telnet 127.0.0.1 59999

        System.out.println("Netty Server start...");

    }
}

HelloHandle.java

package morning.cat.netty3.x.handle;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;

/**
 * @describe: Netty3.x Server Handle
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class HelloHandle extends SimpleChannelHandler {
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
        String message = new String(channelBuffer.array());
        System.out.println("接收消息:" + message);

        ChannelBuffer writeMsg = ChannelBuffers.copiedBuffer((" 已接收消息" + message).getBytes());
        ctx.getChannel().write(writeMsg);

        super.messageReceived(ctx, e);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("发生异常");
        //super.exceptionCaught(ctx, e);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("新客户端打开连接" + ctx.getName());
        super.channelConnected(ctx, e);
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭连接");
        super.channelDisconnected(ctx, e);
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭通道");
        super.channelClosed(ctx, e);
    }
}

客户端
package morning.cat.netty3.x.client;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @describe: Netty3.x Client
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class NettyClient {

    public static void main(String[] args) {

        // 客户端
        ClientBootstrap bootstrap = new ClientBootstrap();

        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService work = Executors.newCachedThreadPool();

        // 设置 ChannelFactory 工厂
        bootstrap.setFactory(new NioClientSocketChannelFactory(boss, work));

        // 设置管道工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {

                // 获取管道
                ChannelPipeline channelPipeline = Channels.pipeline();

                // Channel Pipeline

                // 接收信息转换成string(上行)
                channelPipeline.addLast("StringDecoder", new StringDecoder());
                // 回写直接写入字符串
                channelPipeline.addLast("StringEncoder", new StringEncoder());

                channelPipeline.addLast("ClientHandle", new ClientHandle());
                return channelPipeline;
            }
        });

        // 绑定端口
        ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("127.0.0.1", 59999));
        System.out.println("Netty Client start...");

        Channel channel = channelFuture.getChannel();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入:");
            channel.write(scanner.next());
        }

    }
}

ClientHandle.java

package morning.cat.netty3.x.client;

import org.jboss.netty.channel.*;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class ClientHandle extends SimpleChannelHandler {
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("接收消息:" + e.getMessage());

        super.messageReceived(ctx, e);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("发生异常");
        super.exceptionCaught(ctx, e);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("打开连接");
        super.channelConnected(ctx, e);
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭连接");
        super.channelDisconnected(ctx, e);
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭通道");
        super.channelClosed(ctx, e);
    }
}

Netty4 的一些简单实践

服务端

NettyServer.java

package morning.cat.netty4.x;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * @describe: Netty4.x Server
 * @author: morningcat.zhang
 * @date: 2019/4/23 12:13 AM
 */
public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        // 用来处理I/O操作的多线程事件循环器
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {

            // 服务端
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            // 设置 NioSocket 工厂
            serverBootstrap.group(bossGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);

            // 设置管道工厂 ChannelHandler
            serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel channel) throws Exception {

                    ChannelPipeline channelPipeline = channel.pipeline();
                    // 接收信息转换成string(上行)
                    // channelPipeline.addLast("StringDecoder", new StringDecoder());
                    // 回写直接写入字符串
                    // channelPipeline.addLast("StringEncoder", new StringEncoder());

                    //
                    //channelPipeline.addLast("EchoServerHandle", new EchoServerHandle());
                    //
                    // channelPipeline.addLast("HelloHandle", new HelloHandle());

                    //
                    channelPipeline.addLast("HelloHandle", new EchoServerHandle());

                    // channelPipeline.addLast("TimeServerHandler", new TimeServerHandler());
                }
            });

            // 设置参数
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口
            // telnet 127.0.0.1 51001
            // Bind and start to accept incoming connections.
            ChannelFuture channelFuture = serverBootstrap.bind(51001).sync();
            System.out.println("Netty4 Server start...");


            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            channelFuture.channel().closeFuture().sync();
            System.out.println("closeFuture");
        } finally {
            // 关闭资源
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }
}

EchoServerHandle.java

package morning.cat.netty4.x.server.handle;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;

import java.nio.charset.Charset;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/23 3:41 PM
 * @see ChannelOutboundHandlerAdapter,ChannelInboundHandlerAdapter
 */
public class EchoServerHandle extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelInactive");
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead ----->");
        if (msg instanceof ByteBuf) {
            ByteBuf byteBuf = (ByteBuf) msg;
            System.out.println(byteBuf.toString(Charset.defaultCharset()));

        }


        //ByteBuf byteBuf = ByteBufUtil.writeUtf8(ByteBufAllocator.DEFAULT, "server已收到此消息\n");
        //ctx.write(byteBuf);
        //super.channelRead(ctx, msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete");

//        Channel channel = ctx.channel();
//        channel.writeAndFlush();

        ctx.flush();
        //super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("exceptionCaught");
        super.exceptionCaught(ctx, cause);
    }

}

客户端
package morning.cat.netty4.x.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import morning.cat.netty4.x.client.handle.ClientHandle;
import morning.cat.netty4.x.client.handle.EchoClientHandler;

import java.util.Scanner;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/23 3:23 PM
 */
public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        // 用来处理I/O操作的多线程事件循环器
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {

            // 客户端
            Bootstrap clientBootstrap = new Bootstrap();

            // 设置 NioSocket 工厂
            clientBootstrap.group(workerGroup);
            clientBootstrap.channel(NioSocketChannel.class);


            // 设置管道工厂
            clientBootstrap.handler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel channel) throws Exception {

                    ChannelPipeline channelPipeline = channel.pipeline();
                    channelPipeline.addLast("ClientHandle", new EchoClientHandler());
                }
            });

            // 设置参数
            clientBootstrap.option(ChannelOption.SO_BACKLOG, 128);

            // 连接服务端
            ChannelFuture channelFuture = clientBootstrap.connect("127.0.0.1", 51001).sync();
            System.out.println("Netty4 Client start...");


            //channelFuture.channel().closeFuture().sync();

//            Channel channel = channelFuture.channel();
//            Scanner scanner = new Scanner(System.in);
//            while (true) {
//                System.out.print("请输入:");
//                String ss = scanner.next();
//                if (ss.equals("exit")) {
//                    break;
//                }
//                channel.writeAndFlush(ss);
//            }


        } finally {
            // 关闭资源
            workerGroup.shutdownGracefully();
        }
    }
}

package morning.cat.netty4.x.client.handle;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/9/24 2:34 PM
 */
public class EchoClientHandler extends ChannelInboundHandlerAdapter {

    private final ByteBuf firstMessage;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler() {
        firstMessage = Unpooled.buffer(128);
//        for (int i = 0; i < firstMessage.capacity(); i++) {
//            firstMessage.writeByte((byte) i);
//        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        firstMessage.writeBytes("HelloNetty".getBytes());
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

附录


对于并发编程网netty5指南,最好结合Netty提供的example工程对比着进行学习及实践。

对于并发编程网上的关于Netty的文章,有些还是值得慢慢学习的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值