Netty即是服务端又是客户端,服务端和客户端相互对应。

具体功能细节是:

上游有一个服务,会主动发送消息给我中间件平台。中间件平台既有服务端也有客户端。通过下游客户端连接进来的客户端和中间件传下去的通道id是一样的,实现互相对应的一种通道,保证知道传输的消息是走的同一条路。那么就要自己具备同时是一个服务端和一个客户端,下游客户端连接服务端。也就是达到一种透传的功能,中间件平台只充当消息转换的平台,不做任何转换。

针对上面的功能细节实现代码思路是:将上游下发的数据和自己本身的连接数据以及下游客户端连接数据都使用全局map存储,在map中获取对应通道id和数据。

第一步:监听是否有下游客户端连入,创建客户端连接

public class NettyClientListener implements ApplicationRunner {@AutowiredNettyClient NettyClient;@Overridepublic void run(ApplicationArguments args) {log.info("Netty Client connection is starting ........................................");//自己本身作为客户端创建的一个客户端连接Channel channel = cGSNettyClient.newClient();CommonDataContext.putChannel(CommonDataContext.CGS_CHANNEL_KEY, channel);log.info("Netty Client channel id = {}", channel.id());}
}

第二步:初始化新的连接

public class NettyClient {public void init() {client = new Bootstrap();EventLoopGroup group = new NioEventLoopGroup();//绑定客户端通道client.channel(NioSocketChannel.class);client.option(ChannelOption.SO_KEEPALIVE, true).option(ChannelOption.TCP_NODELAY, true);client.group(group);client.remoteAddress(host, port);//给NioSocketChannel初始化handler,处理读写事件client.handler(new ChannelInitializer<NioSocketChannel>() { // 通道是NioSocketChannel@Overrideprotected void initChannel(NioSocketChannel ch) {ch.pipeline().addLast(new IdleStateHandler(5, 5, 0));ch.pipeline().addLast(new ByteArrayDecoder());// 增加handlerch.pipeline().addLast(new ClientHandler(applicationContext));}});}public Channel newClient() {try {if (client == null) {init();}// 连接服务器ChannelFuture channelFuture = client.connect(host, port).sync();channelFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture arg0) throws Exception {if (channelFuture.isSuccess()) {log.info("Netty client connection is successful ........................................");} else {log.info("Netty client connection is failed ........................................");channelFuture.cause().printStackTrace();}}});return channelFuture.channel();} catch (Exception e) {log.error("Netty client connection is failed ........................................, because: {}", e.getMessage());return null;}}
}

第三部:通道连接,读写,销毁

public class YJServerHandler extends ChannelInboundHandlerAdapter {/**** 通道下线(连接断开)* @param ctx*/@Overridepublic void channelInactive(ChannelHandlerContext ctx) {Channel hardwareChannel = ctx.channel();//客户端通道IDString hardwareChannelId = ctx.channel().id().asLongText();//中间件的客户端也需要关闭Channel ccChannel = CommonDataContext.getChannel(hardwareChannelId);//客户端ID查询对应的中间件通道IDString ccChannelId = ccChannel.id().asLongText();CommonDataContext.removeChannel(hardwareChannelId);CommonDataContext.removeChannel(ccChannelId);ccChannel.disconnect();hardwareChannel.disconnect();}/*** 通道激活,客户端通道激活的同时,中间件也创建和激活一个客户端通道;* @param ctx*/@Overridepublic void channelActive(ChannelHandlerContext ctx) {NettyClient NettyClient = SpringContextUtils.getBean(NettyClient.class);Channel channel = ctx.channel();//客户端通道激活的同时,(中间件)也创建一个客户端;Channel cccClientChannel = ccNettyClient.newClient();CommonDataContext.putChannel(channel.id().asLongText(), ccClientChannel);CommonDataContext.putChannel(ccClientChannel.id().asLongText(), channel);log.info("logictis channelActive ChannelMap = {}, 客户端地址及端口号:{}", CommonDataContext.getChannelMap(), ctx.channel().remoteAddress());}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//获取中间件的通道Channel channel = CommonDataContext.getChannel(ctx.channel().id().asLongText());//log.info("SocketHandler channel = {}", channel);channel.writeAndFlush(msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {cause.printStackTrace();ctx.close();}@Overridepublic void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {super.userEventTriggered(ctx, evt);if (evt instanceof IdleStateEvent) {IdleStateEvent event = (IdleStateEvent) evt;if (IdleState.READER_IDLE.equals(event.state())) {log.warn("暂时没有接收到数据");// 可以选择重新连接} else if (IdleState.WRITER_IDLE.equals(event.state())) {log.warn("暂时没有发送数据");// 发送心跳包// ctx.writeAndFlush(MessageProto.Message.newBuilder().setType(1));} else if (event.state().equals(IdleState.ALL_IDLE)) {// 重新连接和log.warn("暂时没有接收或发送数据");}}}
}

第四部:监测

public class XYServerPipeline extends ChannelInitializer<SocketChannel> {@Overridepublic void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new ByteArrayEncoder());// 空闲状态处理器,检测通信Channel的读写状态是否超时,实现心跳检测pipeline.addLast("idleStateHandler", new IdleStateHandler(180, 180, 180, TimeUnit.SECONDS));pipeline.addLast(new XYServerHandler());}
}

第五步:实现业务读取并下发到下游客户端

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//向客户端发送消息,并获取到消息结果,在返回给上游;Channel channel = CommonDataContext.getChannel(ctx.channel().id().asLongText());log.info("ClientHandler channel = {}", channel);channel.writeAndFlush(msg);return;
}

Netty即是服务端又是客户端,服务端和客户端相互对应相关推荐

  1. Netty实战 IM即时通讯系统(九)实现客户端登录

    ## Netty实战 IM即时通讯系统(九)实现客户端登录 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向通信 数据传输载 ...

  2. Netty的Socket编程详解-搭建服务端与客户端并进行数据传输

    场景 Netty在IDEA中搭建HelloWorld服务端并对Netty执行流程与重要组件进行介绍: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article ...

  3. Netty实战 IM即时通讯系统(十)实现客户端和服务端收发消息

    Netty实战 IM即时通讯系统(十)实现客户端和服务端收发消息 零. 目录 IM系统简介 Netty 简介 Netty 环境配置 服务端启动流程 客户端启动流程 实战: 客户端和服务端双向通信 数据 ...

  4. Asp.net webApi 通过WebSocket推送消息给客户端,搭建一个即是服务端又是客户端的服务

    Asp.net webApi 通过WebSocket推送消息给客户端,搭建一个即是服务端又是客户端的服务_IT_ziliang的博客-CSDN博客 WebSocket是一种在单个TCP连接上进行全双工 ...

  5. MySQL数据库介绍、安装(服务端软件安装、客户端软件安装(图形化界面客户端和命令行客户端))

    1. MySQL数据库的介绍 MySQL是一个关系型数据库管理系统,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System, ...

  6. android从服务端获取json解析显示在客户端上面,Android服务端获取json解析显示在客户端上面.doc...

    Android服务端获取json解析显示在客户端上面 Android从服务端获取json解析显示在客户端上面 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比 ...

  7. Java:socket服务端,socket服务端支持多连接,socket客户端,socket客户端支持发送和接受

    一.Java之socket服务端 新建一个Java工程 命名 给他先创建一个类 在类里面我们做一个main 这里面也需要,创建套接字,IP号,端口号 但是java中有一个类         Serve ...

  8. 例子 客户端_服务端也是可以主动向客户端推送数据的--WebSocket

    简介 WebSocket是一种在单个TCP连接上进行全双工通信的协议.WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范.WebSocket API也 ...

  9. plsq卸载 删除注册表、_win10操作系统下oracle11g客户端/服务端的下载安装配置卸载总结...

    win10操作系统下oracle11g客户端/服务端的下载安装配置卸载总结 一:前提 注意:现在有两种安装的方式 1. oracle11g服务端(64位)+oracle客户端(32位)+plsql(3 ...

最新文章

  1. 【网络流】解题报告:luogu P3376 【模板】网络最大流
  2. 学习Exchange管理最佳实践
  3. Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
  4. 三个线程按顺序输出数字
  5. 读“产品经理那些事儿”有感
  6. Python设计模式:命令模式
  7. Unicode字符编码查询器。
  8. 开关电源(DC-DC)与LDO电源的区别---效率
  9. 史上最全软件测试Web测试要点,吐血整理。
  10. origin软件画流程图_免费的网络拓扑流程图绘制软件(PaceStar LanFlow)
  11. 在Mysql中无符号是什么意思博客_mysql中的unsigned是什么意思???
  12. 查看当前Ubuntu系统的版本
  13. 2022年西藏最新八大员之(安全员)模拟试题题库及答案
  14. 面向园区网的全数字化网络架构 - Cisco DNA介绍
  15. oracle的left join和inner join的区别
  16. 翻译英语的软件-免费翻译软件-各种语言互相翻译
  17. layui的html页面支持转jsp吗,layui jsp
  18. 镜头光学指标介绍----清晰度SFR/MTF
  19. Bigasoft Video Downloader Pro Mac破解教程
  20. 《C++ 黑客编程揭秘与防范(第2版)》—第6章6.8节KeyMake工具的使用

热门文章

  1. 常用python执行shell的命令
  2. 服务器回收站误删的文件怎么恢复,回收站删除的文件怎么恢复
  3. ChatGPT辅导孩子作业有技巧
  4. 安装和使用ArchLiunx超详细教程
  5. SAP 销售订单批量可用性检查(ATP)
  6. echarts 主副标题不换行
  7. MySQL用like快速查询姓名
  8. Python中ArcPy实现ArcGIS自动批量制图与地图要素批量设置
  9. 三维薄板样条,用于三维模型变形(c++)
  10. 把客户当成自己的朋友 (销售中的心理学)