不用 5 分钟,简单粗暴地快速了解 Netty 构建服务

一、简介

Netty 是一个客户端/服务器框架,它提供了 NIO 网络的简化层。这使得它成为创建低级非阻塞网络应用程序的良好候选者。先看看 Netty 框架的主要亮点:

  1. Netty 比普通的 Java NIO 更易于使用

  2. 只需一个依赖即可获得整个框架(例如使用 Maven)

  3. 具有更好的吞吐量和更低的延迟。由于其内部资源池,它还具有可扩展性。

  4. 完整的 SSL/TLS 和 StartTLS 支持。

二、开始

2.1、在 Maven 工程中添加依赖

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.52.Final</version>
    </dependency>

2.2、创建服务端代码

import java.util.ArrayList;
import java.util.List;

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

public final class NettyServer {

    static final int PORT = 8888;

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

        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();

                            p.addLast(new StringDecoder());
                            p.addLast(new StringEncoder());

                            p.addLast(new ServerHandler());
                        }
                    });

            ChannelFuture f = b.bind(PORT).sync();
            //System.out.println("Netty 服务已启动.");

            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

@Sharable
class ServerHandler extends SimpleChannelInboundHandler<String> {

    static final List<Channel> channels = new ArrayList<Channel>();

    @Override
    public void channelActive(final ChannelHandlerContext ctx) {
        channels.add(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, String msg) throws Exception {
        for (Channel c : channels) {
            c.writeAndFlush("Hello " + msg + '\n');
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
    }
}

(1)示例使用了两个 EventLoopGroup。第一个是 boostrap 服务器,第二个是 Worker Group。这是一种常见的最佳实践,以便您可以针对高负载调整特定组并检测瓶颈。

(2)请注意 Handler 上的 @Sharable 注解:这意味着您可以注册并与多个客户端共享它。

2.3、创建客户端代码

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;


public final class NettyClient {

    static final String HOST = "127.0.0.1";
    static final int PORT = 8888;
 
 
    public static void main(String[] args) throws Exception { 
     
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();

                            p.addLast(new StringDecoder());
                            p.addLast(new StringEncoder());
 
                            p.addLast(new  ClientHandler());
 
                        }
                    });

            ChannelFuture f = b.connect(HOST, PORT).sync();

            String input = "您好!";
            Channel channel = f.sync().channel();
            channel.writeAndFlush(input);
            channel.flush();
             
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
}

class ClientHandler extends SimpleChannelInboundHandler<String> {  

    @Override
    protected void channelRead(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("来自服务端的消息: " + msg);
    
    }
    
}

2.4、运行说明

使用 Maven 或 开发工具先运行服务端,然后再运行客户端即可。

两个都是 main 类,你可以考虑在 maven 中配置引导,有智能开发工具的就不用。

一般情况下,业务逻辑都在 ChannelInboundHandler 处编写!

三、扩展知识

3.1、为什么使用 telnet 连接后,输入一个字母它就输出两个出来

非常有可能你使用 Windows 的 telnet 来测试,传说中是 '\r\n‘ 和 '\n' 的原因,但这个问题我还是建议打开 linux 版的 telnet,或其它一些网络工具。其实都自己写客户端了,先不用考虑这个了。

3.2、Maven 如何运行指定 main 类

在 pom 中添加如下类似片断:(注意 mainClass 要跟你的包路径一致)

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.6.0</version>
            <configuration>
                <mainClass>com.example.MainClass</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

3.3、还有一个 mina,用哪个好?

Netty 和 MINA 都是Java平台上的高性能网络通信框架,它们都提供了异步非阻塞的API来简化网络程序的开发。(一般首选 netty,从设计、文档、性能、社区等相比较的结果。)

Netty

  • 性能:Netty是目前业界公认的高性能网络编程框架之一,它的性能通常被认为比MINA更好。
  • 社区和支持:Netty有一个非常活跃的社区,很多知名的开源项目(如Apache Dubbo、gRPC)都在使用Netty。因此,如果你在开发过程中遇到问题,更容易找到解决方案或者获得帮助。
  • 文档和资源:Netty的文档和网络上的资源比MINA更丰富,这使得学习和使用Netty相对容易一些。
  • 功能和灵活性:Netty提供了更多的功能和更高的灵活性,它支持更多的协议和数据处理方式。

MINA

  • 简单易用:MINA的设计初衷是简单易用,它提供了一套比较简洁的API,对于一些不需要极致性能的应用,MINA的简单性可能会是一个优势。
  • 轻量级:MINA相对于Netty来说更轻量级,如果你的项目对资源消耗有严格的限制,MINA可能是一个不错的选择。
  • 社区和支持:虽然MINA的社区不如Netty活跃,但它仍然有一定的用户基础和社区支持。

总结

  • 如果你需要极高的性能、更多的功能和更好的社区支持,Netty可能是更好的选择。
  • 如果你的项目相对简单,对性能的要求不是非常高,或者你更偏好简单易用的框架,MINA可能会更适合你。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值