netty的helloworld

一个简单的netty测试,类似聊天。client发送 聊天信息,server 回复client说的话。
运行效果:
client
在这里插入图片描述
service
在这里插入图片描述

1,引用jar包

        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>${netty-all.version}</version>
        </dependency>

2,client 客户端

client.java

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public final class Client {
    public static void main(String[] args) throws Exception {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            //Bootstrap :一个 Netty 应用通常由一个 Bootstrap 开始,主要作用是配置整个 Netty 程序,串联各个组件.
            // Netty 中 Bootstrap 类是客户端程序的启动引导类,ServerBootstrap 是服务端启动引导类。
            Bootstrap b = new Bootstrap();
            //EventLoopGroup :主要管理 eventLoop 的生命周期,可以理解为一个线程池,内部维护了一组线程,
            // 每个线程(NioEventLoop)负责处理多个 Channel 上的事件,而一个 Channel 只对应于一个线程
            b.group(group)
                    .channel(NioSocketChannel.class)
                    //配置 处理 Channel【 I/O 事件或拦截 I/O 】的处理器
                    .handler(new ClientInitializer());
            //Channel : Netty 网络通信的组件,能够用于执行网络 I/O 操作
            Channel ch = b.connect("127.0.0.1", 8888).sync().channel();


            ChannelFuture lastWriteFuture = null;
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            for (; ; ) {
                String line = in.readLine();
                if (line == null) {
                    break;
                }
                // 给服务器发送信息
                lastWriteFuture = ch.writeAndFlush(line + "\r\n");
                // If user typed the 'bye' command, wait until the server closes
                // the connection.
                if ("bye".equals(line.toLowerCase())) {
                    ch.closeFuture().sync();
                    break;
                }
            }

            // Wait until all messages are flushed before closing the channel.
            if (lastWriteFuture != null) {
                lastWriteFuture.sync();
            }
        } finally {
            group.shutdownGracefully();
        }
    }
}

ClientInitializer.java 设置Channel的Handler集合


import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;


public class ClientInitializer extends ChannelInitializer<SocketChannel> {
    private static final StringDecoder DECODER = new StringDecoder();
    private static final StringEncoder ENCODER = new StringEncoder();

    private static final ClientHandler CLIENT_HANDLER = new ClientHandler();


    @Override
    public void initChannel(SocketChannel ch) {
        //ChannelPipline : 保存 ChannelHandler 的 List,用于处理或拦截 Channel 的入站事件和出站操作。
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        // DECODER : IO 的 入站解码器
        pipeline.addLast(DECODER);
        // DECODER : IO 的 出站编码器
        pipeline.addLast(ENCODER);
        //添加自定义的 Channel 处理器 ClientHandler
        pipeline.addLast(CLIENT_HANDLER);
    }
}

ClientHandler.java 自定义Handler,接受server返回的信息并处理


import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

@Sharable
public class ClientHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 接受server返回的信息
     *
     * @param ctx 保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象。
     * @param msg 信息
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.err.println(msg);
    }

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

2,server服务器

Server.java


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public final class Server {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //ServerBootstrap 是服务端启动引导类,主要作用是配置整个 Netty 程序,串联各个组件
            ServerBootstrap b = new ServerBootstrap();
            //boosGroup 用于 Accetpt client连接建立事件并分发请求
            //workerGroup workerGroup 用于处理 I/O 读写事件和业务逻辑
            b.group(bossGroup, workerGroup)
                    //Channel : Netty 网络通信的组件,能够用于执行网络 I/O 操作
                    .channel(NioServerSocketChannel.class)
                    //打印日志
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 配置入站、出站事件handler
                    .childHandler(new ServerInitializer());
            ChannelFuture f = b.bind(8888);
            f.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

2,ServerInitializer.java 配置入站、出站事件handler集合


import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class ServerInitializer extends ChannelInitializer<SocketChannel> {
    private static final StringDecoder DECODER = new StringDecoder();
    private static final StringEncoder ENCODER = new StringEncoder();

    private static final ServerHandler SERVER_HANDLER = new ServerHandler();


    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // 添加 文本行编解码 
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        // DECODER : IO 的 入站解码器
        pipeline.addLast(DECODER);
        // DECODER : IO 的 出站编码器
        pipeline.addLast(ENCODER);
        // 添加自己的 ServerHandler
        pipeline.addLast(SERVER_HANDLER);
    }
}

3,ServerHandler 自定义Handler,用于处理client发送来的信息


import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.net.InetAddress;
import java.util.Date;


@Sharable
public class ServerHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 新链接接通时
     *
     * @param ctx 保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象。
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 为新连接发送庆祝
        ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
        ctx.write("It is " + new Date() + " now.\r\n");
        ctx.flush();
    }

    /**
     * 接受client的信息
     *
     * @param ctx     保存 Channel 相关的所有上下文信息,同时关联一个 ChannelHandler 对象。
     * @param request client的请求
     * @throws Exception
     */
    @Override
    public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
        // Generate and write a response.
        String response;
        boolean close = false;
        if (request.isEmpty()) {
            response = "Please type something.\r\n";
        } else if ("bye".equals(request.toLowerCase())) {
            response = "Have a good day!\r\n";
            close = true;
        } else {
            response = "Did you say '" + request + "'?\r\n";
        }

        ChannelFuture future = ctx.write(response);

        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

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

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

想更详细了解netty,推荐文章:https://www.cnblogs.com/imstudy/p/9908791.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值