netty 4.1.45 第一个netty程序

偏执的太偏执、 2023-07-04 04:56 29阅读 0赞

文章目录

  • 概述
  • maven依赖
  • 服务端
  • 客户端
  • 运行结果

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

概述

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

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

maven依赖

  1. <dependency>
  2. <groupId>io.netty</groupId>
  3. <artifactId>netty-all</artifactId>
  4. <version>4.1.45.Final</version>
  5. </dependency>

服务端

  1. package com.example;
  2. import io.netty.bootstrap.ServerBootstrap;
  3. import io.netty.buffer.ByteBuf;
  4. import io.netty.buffer.Unpooled;
  5. import io.netty.channel.*;
  6. import io.netty.channel.nio.NioEventLoopGroup;
  7. import io.netty.channel.socket.SocketChannel;
  8. import io.netty.channel.socket.nio.NioServerSocketChannel;
  9. public class MyNettyServer {
  10. public static void main(String[] args) {
  11. //配置服务端NIO线程组
  12. EventLoopGroup bossGroup = new NioEventLoopGroup();
  13. EventLoopGroup workGroup = new NioEventLoopGroup();
  14. try {
  15. ServerBootstrap serverBootstrap = new ServerBootstrap();
  16. serverBootstrap.group(bossGroup, workGroup)//配置主从线程组
  17. .channel(NioServerSocketChannel.class)
  18. .option(ChannelOption.SO_BACKLOG, 1024)//配置一些TCP的参数
  19. .childHandler(new MyChildHandler());//添加自定义的channel
  20. //绑定8080端口
  21. ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
  22. //服务端监听端口关闭
  23. ChannelFuture future = channelFuture.channel().closeFuture().sync();
  24. } catch (Exception e) {
  25. e.printStackTrace();
  26. } finally {
  27. //netty优雅停机
  28. bossGroup.shutdownGracefully();
  29. workGroup.shutdownGracefully();
  30. }
  31. }
  32. }
  33. class MyChildHandler extends ChannelInitializer<SocketChannel> {
  34. @Override
  35. protected void initChannel(SocketChannel socketChannel) {
  36. //将自定义的channelhandler添加到channelpipeline的末尾
  37. socketChannel.pipeline().addLast(new TimeServerHandler());
  38. }
  39. }
  40. /** * TimeServerHandler这个才是服务端真正处理请求的服务方法 */
  41. class TimeServerHandler extends ChannelInboundHandlerAdapter {
  42. @Override
  43. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  44. //将请求入参转为ByteBuf对象
  45. ByteBuf byteBuf = (ByteBuf) msg;
  46. byte[] bytes = new byte[byteBuf.readableBytes()];
  47. byteBuf.readBytes(bytes);
  48. //由于我们这里传的参数是string,所以直接强制转换
  49. String body = new String(bytes, "UTF-8");
  50. System.out.println("收到客户端请求:" + body);
  51. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  52. String currentTimeStr = "QUERY TIME ORDER".equalsIgnoreCase(body) ?
  53. format.format(new Date()) + "" : "BAD ORDER";
  54. ByteBuf resp = Unpooled.copiedBuffer(currentTimeStr.getBytes());
  55. ctx.write(resp);
  56. }
  57. @Override
  58. public void channelReadComplete(ChannelHandlerContext ctx) {
  59. ctx.flush();
  60. }
  61. @Override
  62. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
  63. ctx.close();
  64. }
  65. }

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

客户端

  1. package com.example;
  2. import io.netty.bootstrap.Bootstrap;
  3. import io.netty.buffer.ByteBuf;
  4. import io.netty.buffer.Unpooled;
  5. import io.netty.channel.*;
  6. import io.netty.channel.nio.NioEventLoopGroup;
  7. import io.netty.channel.socket.SocketChannel;
  8. import io.netty.channel.socket.nio.NioSocketChannel;
  9. public class MyNettyClient {
  10. public static void main(String[] args) {
  11. //客户端NIO线程组
  12. EventLoopGroup group = new NioEventLoopGroup();
  13. try {
  14. Bootstrap bootstrap = new Bootstrap();
  15. bootstrap.group(group)
  16. .channel(NioSocketChannel.class)
  17. .handler(new ChannelInitializer<SocketChannel>() {
  18. @Override
  19. protected void initChannel(SocketChannel ch) {
  20. ch.pipeline().addLast(new TimeClientHandler());
  21. }
  22. });
  23. //异步链接服务器
  24. ChannelFuture future = bootstrap.connect("127.0.0.1", 8080).sync();
  25. //等等客户端链接关闭
  26. future.channel().closeFuture().sync();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. } finally {
  30. //优雅停机
  31. group.shutdownGracefully();
  32. }
  33. }
  34. }
  35. //客户端业务逻辑处理类
  36. class TimeClientHandler extends ChannelInboundHandlerAdapter {
  37. /** * 客户端与服务器TCP链路链接成功后调用该方法 * @param ctx */
  38. @Override
  39. public void channelActive(ChannelHandlerContext ctx) {
  40. byte[] req = "QUERY TIME ORDER".getBytes();
  41. ByteBuf firstMsg = Unpooled.buffer(req.length);
  42. firstMsg.writeBytes(req);
  43. ctx.writeAndFlush(firstMsg);//写入缓冲并且发送到socketchannel
  44. }
  45. /** * 读取到服务端相应后执行该方法 * @param ctx * @param msg * @throws Exception */
  46. @Override
  47. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  48. ByteBuf byteBuf = (ByteBuf) msg;
  49. byte[] bytes = new byte[byteBuf.readableBytes()];
  50. byteBuf.readBytes(bytes);
  51. String body = new String(bytes, "UTF-8");
  52. System.out.println("服务端返回:"+body);
  53. }
  54. @Override
  55. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  56. System.out.println("Unexpected exception from downstream : " + cause.getMessage());
  57. ctx.close();
  58. }
  59. }

运行结果

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,29人围观)

还没有评论,来说两句吧...

相关阅读