学习netty之服务通信

博客围绕Java开发展开,介绍了依赖相关内容,详细阐述了构建服务端时自定义消息处理器的方法,还说明了客户端的构建过程,最后提及了测试环节,为Java开发提供了实践指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、依赖

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

2、构建服务端

public class NettyServer {

    private static final Logger logger = LoggerFactory.getLogger(NettyServer.class);

    private static String host="127.0.0.1";
    private static int port = 12345;

    public NettyServer(String serverAddress){
        if(StringUtils.isNotBlank(serverAddress)){
            String[] split = serverAddress.split(":");
            this.host = split[0];
            this.port = Integer.parseInt(split[1]);
        }
    }


    public static void startNettyServer() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel channel) throws Exception {
                            channel.pipeline()
                                    .addLast(new StringDecoder())
                                    .addLast(new StringEncoder())
                                    .addLast(new NettyServerHandler());
                        }
                    }).option(ChannelOption.SO_BACKLOG,128)
                    .childOption(ChannelOption.SO_KEEPALIVE,true);
            ChannelFuture future = bootstrap.bind(host, port);
            logger.info("server start on {}:{}",host,port);
            future.channel().closeFuture().sync();
        }catch (Exception e){
            logger.error("RPC server start error " ,e);
        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

自定义一个消息处理器

public class NettyServerHandler extends SimpleChannelInboundHandler<Object> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {

        logger.info("服务端收到的消息为================{}", JSONObject.toJSONString(o));
    }
}

3、构建客户端

public class NettyClient {

    private static final Logger logger = LoggerFactory.getLogger(NettyClient.class);

    private final Bootstrap bootstrap;
    private final EventLoopGroup eventLoopGroup;

    private static volatile NettyClient instance;

    private static Map<String, NettyClientHandler> handlerMap = new ConcurrentHashMap<>();

    private NettyClient(){
        bootstrap = new Bootstrap();
        eventLoopGroup = new NioEventLoopGroup(4);
         bootstrap.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>(){

                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        channel.pipeline()
                                .addLast(new StringDecoder())
                                .addLast(new StringEncoder())
                                .addLast(new NettyClientHandler());
                    }
                });    }

    public static NettyClient getInstance(){
        if(instance == null){
            synchronized (NettyClient.class){
                if(instance == null){
                    instance = new NettyClient();
                }
            }
        }
        return instance;
    }

    public  void sendMsg(String message) throws Exception {
        String serverAddress = "127.0.0.1";
        int port = 12345;
        String key = serverAddress.concat("_").concat(String.valueOf(port));
        NettyClientHandler handler = handlerMap.get(key);
        if(handler == null){
            handler = getNettyClientHandler(serverAddress,port);
            handlerMap.put(key,handler);
        }else if(!handler.getChannel().isActive()){
            //存在,但是不活跃
            handler.close();
            handler = getNettyClientHandler(serverAddress,port);
            handlerMap.put(key,handler);
        }
        handler.sendMsg(message);
    }

    private NettyClientHandler getNettyClientHandler(String serverAddress, int port) throws Exception{
        ChannelFuture channelFuture = bootstrap.connect(serverAddress, port).sync();
        channelFuture.addListener((ChannelFutureListener) listener->{
            if(channelFuture.isSuccess()){
                logger.info("connect rpc server {} on port {} success ",serverAddress,port);
            }else{
                logger.error("connect rpc server {} on port {} failed ",serverAddress,port);
                channelFuture.cause().printStackTrace();
                eventLoopGroup.shutdownGracefully();
            }
        });
        return channelFuture.channel().pipeline().get(NettyClientHandler.class);
    }
}
public class NettyClientHandler extends SimpleChannelInboundHandler<Object> {

    private static final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);

    private volatile Channel channel;

    private SocketAddress remotePeer;

    public Channel getChannel() {
        return channel;
    }

    public SocketAddress getRemotePeer() {
        return remotePeer;
    }

    /**
     * 注册
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        logger.info("channelRegistered--------------");
        super.channelRegistered(ctx);
        this.channel = ctx.channel();
    }

    /**
     * 激活
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        this.remotePeer = this.channel.remoteAddress();
        logger.info("channelActive--------------");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
        logger.info("channelRead0--------------"+Thread.currentThread().getName());
        logger.info("消费者接收到的消息为{}", JSONObject.toJSONString(o));
    }

    public void sendMsg(String message){
        channel.writeAndFlush(message);
    }

    public void close(){
        channel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }

}

4、测试

public class NettyTest {

    public static void main(String[] args) {

        new Thread(()->{
            NettyServer.startNettyServer();
        }).start();

        new Thread(()->{
            NettyClient instance = NettyClient.getInstance();
            try {
                while (true){
                    Thread.sleep(2000);
                    instance.sendMsg(UUID.randomUUID().toString());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }).start();
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值