Netty简单实现服务端和客户端并通信

 服务端NettyServer:

①根据前面说到的Netty架构,对于服务端,我们也需要先新建两个NioEventLoopGroup,分别是boos和worker,boos是负责进行连接请求的接收accept事件,而worker则是负责业务处理

//创建bossGroup和workerGroup,这两个都是无限循环
//只是处理连接请求accept,含有的子线程有多少个呢,NioEventLoop个数,默认是cpu的核数*2
NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
//真正的和客户端进行业务处理,含有的子线程有多少个呢,NioEventLoop个数,默认是cpu的核数*2
NioEventLoopGroup workerGroup = new NioEventLoopGroup();

②创建完上面两个线程组之后,则需要创建一个服务端启动对象,配置启动参数

ServerBootstrap serverBootstrap = new ServerBootstrap();

下面使用链式编程来进行配置:

serverBootstrap.group(bossGroup, workerGroup)//设置两个线程组                             .channel(NioServerSocketChannel.class)//使用nioserversocketchannel作为通道实现           .option(ChannelOption.SO_BACKLOG, 128)//设置线程队列等待连接个数           .childOption(ChannelOption.SO_KEEPALIVE, true)//设置保持连接状态         .childHandler(new ChannelInitializer<SocketChannel>() {//创建通道测试对象(匿名对象)piepline里面设置处理器

    //这里会进行客户端业务处理
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        //这里加入了自定义的handler
        ChannelPipeline pipeline = ch.pipeline().addLast(new NettyServerHandler());//通过chnnel可以得到pipeline
    }
});//给workergruop的eventgroup设置处理器

※这里比较重要的是最后一步的childHandler,这里的childHandler就是给我们的workerloop实际处理业务逻辑的pipeline配置一个handler,handler可以定制化逻辑。

//绑定一个端口,并且同步,生成一个channelfuture对象,后面会详聊,简单的认为是立马返回的对象,
//这里就是启动服务器,因为绑定了端口
ChannelFuture channelFuture = serverBootstrap.bind(6668).sync();
//对关闭通道进行监听,当有关闭通道的消息的时候,才会进行close
channelFuture.channel().closeFuture().sync();
finally {
  //优雅的关闭
    bossGroup.shutdownGracefully();
    workerGroup.shutdownGracefully();
}

上面就是netty简单的实现了服务端,下面看下自定义的handler是怎样实现的:

//自定义的适配器需要继承netty自己的适配器,这样我们自定义的handler才能称为handler
public class NettyServerHandler extends ChannelInboundHandlerAdapter
Netty自己的handler有几个主要的方法:

(1)channelRead,这个方法当有数据读写的时候,会触发,可以读取客户端的消息
channelRead(ChannelHandlerContext ctx, Object msg)

里面有两个参数传入,一个是ChannelHandlerContext--上下文对象,包含了管道pipeline,通道channel,地址remoteAdress等信息

一个是Object,就是客户端发送过来的对象,因为数据是在channel中,所以我们最好使用buffer来进行接收,因此一般我们都需要对msg进行强转

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

    System.out.println("server ctx:"+ ctx);
    System.out.println("看看channel和pipeline关系");
    Channel channel = ctx.channel();
    ChannelPipeline pipeline = ctx.pipeline();//本质是双向链表,出栈入栈问题

    //因为现在数据在channel,所以我们最好用buffer接收---这里的buffer跟nio的buffer有区别
    //强转
    ByteBuf buf=  (ByteBuf)msg;
    System.out.println("读取到的数据为:"+ buf.toString(CharsetUtil.UTF_8));
 //   System.out.println("客户端地址:"+ctx.channel().remoteAddress());
}

(2)channelReadComplete,数据读取完毕之后,需要做的业务操作,回消息

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    //把数据write到缓冲区,同时进行flush,就是把缓存数据写到管道
    //一般来讲,我们需要对发送的数据进行编码
    ctx.writeAndFlush(Unpooled.copiedBuffer("hello,客户端",CharsetUtil.UTF_8));
}

(3)exceptionCaught,发生异常的handler

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

服务端NettyClient:

①客户端跟服务端有些许区别,第一个就是不需要两个loopgroup了,不需要使用boosgroup了,所以只需要新建一个loopgroup来处理业务就行了

NioEventLoopGroup eventgruop = new NioEventLoopGroup();

②第二点就是不是使用serverBootstrap,而是使用bootstrap

//客户端使用的是bootstrap
Bootstrap bootstrap = new Bootstrap();

③设置启动参数

//设置相关参数
bootstrap.group(eventgruop)//设置线程组
         .channel(NioSocketChannel.class)//设置客户端通道的实现类
         .handler(new ChannelInitializer<SocketChannel>() {
             @Override
             protected void initChannel(SocketChannel ch) throws Exception {
                 ch.pipeline().addLast(new NettyClientHandler());//加入自己的处理器
             }
         });
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6668).sync();
System.out.println("客户端开始连接");
//给通道关闭进行监听---当发生了通道关闭消息的时候会进行关闭
channelFuture.channel().closeFuture().sync();
finally {
    //优雅的关闭
    eventgruop.shutdownGracefully();
}

下面就是客户端的自定义handler:

(1)channelActive,当通道就绪,就会触发该方法

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    System.out.println("client:"+ctx);
    //发送消息
    ctx.writeAndFlush(Unpooled.copiedBuffer("Hello Server,miao", CharsetUtil.UTF_8));
}

(2)channelRead,当通道有读取事件时,会触发

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

  ByteBuf buf=  (ByteBuf) msg;

  //服务器回复的消息
    System.out.println("客户端收到的消息:"+buf.toString(CharsetUtil.UTF_8));
    System.out.println("服务器的地址:"+ctx.channel().remoteAddress());

}

(3)exceptionCaught,当有异常的就会触发
 

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

                                                                       

Netty Quic是一种基于QUIC(Quick UDP Internet Connections)协议的高性能、低延迟的网络通信框架,它是由Netty项目集成支持的。QUIC是一种由Google设计并维护的下一代传输层协议,旨在改进TCP/IP协议栈的性能,特别是在移动网络环境下。 在Netty实现Quic服务器客户端通信,可以按照以下步骤操作: 1. **添加依赖**:在你的项目中引入Netty的Quic模块,例如如果你使用Maven,需要添加`io.netty:netty-quic`依赖。 2. **创建QuicServer**:服务器端需要创建一个`QuicServerBootstrap`实例,并配置监听地址和处理器链路。 ```java QuicServerBootstrap bootstrap = new QuicServerBootstrap(); bootstrap.group(...); // 设置事件组 bootstrap.channel(NioQuicServerChannel.class); bootstrap.childOption(ChannelOption.AUTO_READ, false); // 配置选项 bootstrap.childHandler(new MyQuicServerHandler()); // 自定义处理程序 bootstrap.bind(...); // 绑定端口 ``` 3. **创建QuicClient**:客户端则需要创建一个`QuicClientBootstrap`实例,设置目标地址,并连接到服务器。 ```java QuicClientBootstrap clientBootstrap = new QuicClientBootstrap(); clientBootstrap.group(...); // 设置事件组 clientBootstrap.channel(NioQuicClientChannel.class); clientBootstrap.handler(new MyQuicClientHandler()); QuicOptions options = new QuicOptions(); // 设置连接选项 options.maxIdleTimeMillis(5000); // 设置最大空闲时间 clientBootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, options.connectTimeoutMillis); clientBootstrap.connect(...); // 连接服务器地址 ``` 4. **自定义Handler**:`MyQuicServerHandler`和`MyQuicClientHandler`是你自己实现的,用于处理数据收发、连接管理和错误处理等任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值