Netty实战(二)第一个Netty程序

本文详细介绍了如何使用Netty构建Echo服务器和客户端。首先,文章讲解了Netty环境准备,需要JDK 1.8+和Apache Maven 3.3.9+。接着,概述了Netty客户端/服务器的交互模式。然后,逐步展示了Echo服务器的构建,包括ChannelHandler的业务逻辑和服务器引导。最后,阐述了Echo客户端的编写,包括ChannelHandler的实现和客户端引导。文章通过示例代码帮助读者理解Netty的工作原理。
摘要由CSDN通过智能技术生成

一、环境准备

Netty需要的运行环境很简单,只有2个。

  • JDK 1.8+
  • Apache Maven 3.3.9+

二、Netty 客户端/服务器概览

在这里插入图片描述
如图,展示了一个我们将要编写的 Echo 客户端和服务器应用程序。该图展示是多个客户端同时连接到一台服务器。所能够支持的客户端数量,在理论上,仅受限于系统的可用资源(以及所使用的 JDK 版本可能会施加的限制)。

Echo 客户端和服务器之间的交互是非常简单的;在客户端建立一个连接之后,它会向服务器发送一个或多个消息,反过来服务器又会将每个消息回送给客户端。虽然它本身看起来好像用处不大,但它充分地体现了客户端/服务器系统中典型的请求-响应交互模式

三、编写 Echo 服务器

所有的 Netty 服务器都需要以下两部分。

  • 至少一个 ChannelHandler—该组件实现了服务器对从客户端接收的数据的处理,即它的业务逻辑。
  • 引导—这是配置服务器的启动代码。至少,它会将服务器绑定到它要监听连接请求的端口上。

3.1 ChannelHandler 和业务逻辑

上一篇博文我们介绍了 Future 和回调,并且阐述了它们在事件驱动设计中的应用。我们还讨论了 ChannelHandler,它是一个接口族的父接口,它的实现负责接收并响应事件通知。

在 Netty 应用程序中,所有的数据处理逻辑都包含在这些核心抽象的实现中。因为你的 Echo 服务器会响应传入的消息,所以它需要实现ChannelInboundHandler 接口,用来定义响应入站事件的方法。简单的应用程序只需要用到少量的这些方法,所以继承 ChannelInboundHandlerAdapter 类也就足够了,它提供了ChannelInboundHandler 的默认实现。

我们将要用到的方法是:

  • channelRead() :对于每个传入的消息都要调用;
  • channelReadComplete() : 通知ChannelInboundHandler最后一次对channelRead()的调用是当前批量读取中的最后一条消息;
  • exceptionCaught() :在读取操作期间,有异常抛出时会调用。

该 Echo 服务器的 ChannelHandler 实现是 EchoServerHandler,如代码:

package com.example.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;

/**
 * @author lhd
 * @date 2023/05/16 15:05
 * @notes Netty Echo服务端简单逻辑
 */

//表示channel可以并多个实例共享,它是线程安全的
@ChannelHandler.Sharable
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
   

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   
        ByteBuf in = (ByteBuf) msg;
        //将消息打印到控制台
        System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
        //将收到的消息写给发送者,而不冲刷出站消息
        ctx.write(in);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
   
        //将未决消息冲刷到远程节点,并且关闭该 Channe
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
                .addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
   
        //打印异常堆栈跟踪
        cause.printStackTrace();
        //关闭该channel
        ctx.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

timi先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值