netty 4.1.45 第一个netty程序

注:更多netty相关文章请访问博主专栏: netty专栏

概述

本系列文章介绍netty的学习。使用的版本是4.1.45
jdk采用Java11

本系列文章由浅入深,先学习使用,再研究其实现原理。
本节编写一个最简单的netty服务器。

maven依赖

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

服务端

package com.example;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class MyNettyServer {
    public static void main(String[] args) {
        //配置服务端NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup)//配置主从线程组
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)//配置一些TCP的参数
                    .childHandler(new MyChildHandler());//添加自定义的channel
            //绑定8080端口
            ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
            //服务端监听端口关闭
            ChannelFuture future = channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //netty优雅停机
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

class MyChildHandler extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) {
        //将自定义的channelhandler添加到channelpipeline的末尾
        socketChannel.pipeline().addLast(new TimeServerHandler());
    }
}

/**
 * TimeServerHandler这个才是服务端真正处理请求的服务方法
 */
class TimeServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        //将请求入参转为ByteBuf对象
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        //由于我们这里传的参数是string,所以直接强制转换
        String body = new String(bytes, "UTF-8");
        System.out.println("收到客户端请求:" + body);

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String currentTimeStr = "QUERY TIME ORDER".equalsIgnoreCase(body) ?
                format.format(new Date()) + "" : "BAD ORDER";
        ByteBuf resp = Unpooled.copiedBuffer(currentTimeStr.getBytes());
        ctx.write(resp);
    }

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

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

这里配置了NIO服务端,采用的是主从线程模型,关于主从模型后续再介绍。
服务端端口是8080.
服务端真正处理客户端请求的方法是com.example.TimeServerHandler#channelRead,该方法的作用是接收请求,返回服务器时间

客户端

package com.example;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;


public class MyNettyClient {
    public static void main(String[] args) {
        //客户端NIO线程组
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(new TimeClientHandler());
                        }
                    });

            //异步链接服务器
            ChannelFuture future = bootstrap.connect("127.0.0.1", 8080).sync();
            //等等客户端链接关闭
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //优雅停机
            group.shutdownGracefully();
        }
    }
}

//客户端业务逻辑处理类
class TimeClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 客户端与服务器TCP链路链接成功后调用该方法
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        byte[] req = "QUERY TIME ORDER".getBytes();
        ByteBuf firstMsg = Unpooled.buffer(req.length);
        firstMsg.writeBytes(req);
        ctx.writeAndFlush(firstMsg);//写入缓冲并且发送到socketchannel
    }

    /**
     * 读取到服务端相应后执行该方法
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        String body = new String(bytes, "UTF-8");
        System.out.println("服务端返回:"+body);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("Unexpected exception from downstream : " + cause.getMessage());
        ctx.close();
    }
}

运行结果

先启动服务器端,再启动客户端。可以看到客户端运行结果:
在这里插入图片描述

OK,第一个netty程序就完成了,上面代码中有一些注释帮助理解运行过程。后续会再写更深入的文章。

注:更多netty相关文章请访问博主专栏: netty专栏

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
包含最新版文档以及全部jar包: jar包如下 netty-buffer-4.1.32.Final-sources.jar netty-buffer-4.1.32.Final.jar netty-build-22-sources.jar netty-build-22.jar netty-codec-4.1.32.Final-sources.jar netty-codec-4.1.32.Final.jar netty-codec-http-4.1.32.Final-sources.jar netty-codec-http-4.1.32.Final.jar netty-codec-http2-4.1.32.Final-sources.jar netty-codec-http2-4.1.32.Final.jar netty-codec-memcache-4.1.32.Final-sources.jar netty-codec-memcache-4.1.32.Final.jar netty-codec-redis-4.1.32.Final-sources.jar netty-codec-redis-4.1.32.Final.jar netty-codec-socks-4.1.32.Final-sources.jar netty-codec-socks-4.1.32.Final.jar netty-codec-stomp-4.1.32.Final-sources.jar netty-codec-stomp-4.1.32.Final.jar netty-common-4.1.32.Final-sources.jar netty-common-4.1.32.Final.jar netty-example-4.1.32.Final-sources.jar netty-example-4.1.32.Final.jar netty-handler-4.1.32.Final-sources.jar netty-handler-4.1.32.Final.jar netty-handler-proxy-4.1.32.Final-sources.jar netty-handler-proxy-4.1.32.Final.jar netty-resolver-4.1.32.Final-sources.jar netty-resolver-4.1.32.Final.jar netty-tcnative-2.0.20.Final-osx-x86_64.jar netty-tcnative-2.0.20.Final-sources.jar netty-transport-4.1.32.Final-sources.jar netty-transport-4.1.32.Final.jar netty-transport-native-epoll-4.1.32.Final-linux-x86_64.jar netty-transport-native-epoll-4.1.32.Final-sources.jar netty-transport-native-kqueue-4.1.32.Final-osx-x86_64.jar netty-transport-native-kqueue-4.1.32.Final-sources.jar netty-transport-native-unix-common-4.1.32.Final-sources.jar netty-transport-native-unix-common-4.1.32.Final.jar netty-transport-rxtx-4.1.32.Final-sources.jar netty-transport-rxtx-4.1.32.Final.jar netty-transport-sctp-4.1.32.Final-sources.jar netty-transport-sctp-4.1.32.Final.jar netty-transport-udt-4.1.32.Final-sources.jar netty-transport-udt-4.1.32.Final.jar

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快乐崇拜234

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值