springboot引入netty

news2024/9/28 21:25:00

配置类

import cn.hutool.core.thread.ThreadUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@Component
@Slf4j
public class NettyServerConfig {

    @Resource
    private BizHandler bizHandler;

    @Value("${netty.port}")
    private int port;


    @PostConstruct
    public void start(){
        ThreadUtil.newSingleExecutor().execute(this::doStart);
    }


    public void doStart(){
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        serverBootstrap.group(bossGroup,workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childHandler(new ChannelInitializer<SocketChannel>(){

                    @Override
                    protected void initChannel(SocketChannel socketChannel) {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addFirst(bizHandler);
                    }
                });

        ChannelFuture channelFuture;
        try {
            channelFuture = serverBootstrap.bind(port).sync();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        channelFuture.addListener(future -> {
            if(future.isSuccess()){
                log.info("netty服务 启动成功");
            }
        });

        ChannelFuture closeFuture = channelFuture.channel().closeFuture();
        try {
            closeFuture.sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }

    }
}

处理器

import com.google.common.collect.Lists;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;


import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Slf4j
@Service
@ChannelHandler.Sharable
public class BizHandler extends ChannelInboundHandlerAdapter {

    private static final String SPACE = " ";

    private static final ConcurrentHashMap<ChannelHandlerContext, String> channelContextMap = new ConcurrentHashMap<>();

    
    public void send(){
        channelContextMap.entrySet().forEach(e -> {

            ChannelHandlerContext context = e.getKey();
            ByteBuf buf = context.alloc().buffer();
            byte[] dataFrame = generateDataFrame();
            buf.writeBytes(dataFrame);
            context.channel().writeAndFlush(buf);
        });
    }


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf buffer = (ByteBuf) msg;
        byte[] bytes = new byte[buffer.readableBytes()];
        buffer.readBytes(bytes);
        String msgHexStr = this.byteArrayToHexString(bytes);
        
        //如果不是预期的连接发过来消息 主动断开连接
        //ctx.channel().close();
        
        ctx.fireChannelRead(msg);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        channelContextMap.remove(ctx);
    }

    private String byteArrayToHexString(byte[] bytes) {
        List<String> dataFrame = Lists.newArrayList();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                // 如果是一位的话,要补0
                hex = "0" + hex;
            }
            dataFrame.add(hex.toUpperCase());
        }
        return dataFrame.stream().collect(Collectors.joining(SPACE));
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174801.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

63.【C语言】再议结构体(上)

1.复习 20.【C语言】初识结构体&#xff08;重要&#xff09; 48.【C语言】结构体补充 2.结构体的特殊声明 01.匿名结构体 *定义 不完全声明,即结构体没有自己的名字(没有结构体标签) *注意事项 1.匿名结构体只能使用一次 2.下列代码合法吗 struct {int a;char b;floa…

使用python获取百度一下,热搜TOP数据详情

一、查找对应链接 # 警告&#xff1a;以下代码仅供学习和交流使用&#xff0c;严禁用于任何违法活动。 # 本代码旨在帮助理解和学习编程概念&#xff0c;不得用于侵犯他人权益或违反法律法规的行为。 1、打开百度页面 百度一下&#xff0c;你就知道 2、点击F12 或 右键鼠标…

text2sql方法:NatSQL和DIN-SQL

NatSQL NatSQL出自2021年9月的论文《Natural SQL: Making SQL Easier to Infer from Natural Language Specifications》(github)&#xff0c;它是一种SQL 中间表征(SQL intermediate representation(IR))方法。 NatSQL作者认为Text2SQL的关键挑战是自然语言描述和其对应的SQ…

Cookie、Session、Token(JWT)还不懂?

Cookie、Session、Token&#xff08;JWT&#xff09; 三者的区别与用途&#xff01;如何进行身份认证&#xff0c;保持用户登录状态&#xff1f; Cookie、Session 和 Token 都是在 Web 开发中用于管理用户状态和进行身份认证的技术&#xff0c;它们之间有以下区别和用途&#…

【js逆向学习】酷我音乐排行榜 python+nodejs(webpack)

逆向目标 目标网址: https://www.kuwo.cn/rankList目标接口: https://www.kuwo.cn/api/www/bang/bang/musicList 加密参数: 参数一&#xff1a;secret参数二&#xff1a;reqId 逆向过程 老规矩先分析网络请求&#xff0c;我们可以分析到网络请求是通过ajax进行的&#xff…

【C++】C/C++内存管理(new/delete)

C/C内存分布 代码内存相关问题 int globalVar 1; static int staticGlobalVar 1;void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)malloc(siz…

yolox训练自己的数据集

环境搭建 gpu按自己情况安装 nvidia-smi 查看自己的版本 CUDA和cudnn 按自己的安装&#xff0c;我的驱动551.76&#xff0c;注意不要用最新的&#xff0c;官网只要求驱动是大于等于&#xff0c;可以用低版本的cuda&#xff0c;我安装的是CUDA 11.1 cuda下载后&#xff0c…

报告查询系统小程序开发制作方案

报告查询小程序系统主要是为了解决传统报告查询方式往往依赖于纸质文档或复杂的内网系统&#xff0c;存在查询效率低、信息更新慢、携带不便等问题。 一、目标用户 企业员工&#xff1a;需要频繁查询各类工作报告&#xff0c;如销售人员查询销售业绩报告&#xff0c;财务人员查…

信道衰落的公式

对于天线&#xff1a; 对于天线的面积计算&#xff1a; 天线的接收功率密度&#xff1a; 天线的接收功率&#xff1a; 移动无线信道&#xff08;I&#xff09; (xidian.edu.cn)https://web.xidian.edu.cn/zma/files/20150710_153736.pdf 更加常用的考虑了额外的信道衰落pathlo…

基于YOLOv5的农作物病虫害识别系统设计与实现(PYQT+web端+微信小程序+YOLOv5+训练数据集+论文+部署文档+开题报告)

摘要 农作物病虫害是农业生产中的关键问题&#xff0c;病虫害的爆发和侵袭不仅严重影响农作物产量和质量&#xff0c;还可引发局部地区严重的灾害性损失。因此&#xff0c;及时发现和预防农作物病虫害的发生和发展至关重要。本文以农作物病虫害图像为载体&#xff0c;运用深度…

python的高级用法

对于python的使用&#xff0c;我们常见的用法是python xx.py直接执行脚本&#xff0c;有时可能您需要在脚本的第一行添加&#xff08;#!/usr/bin/env python3 或 #!/usr/local/bin/python3&#xff09;&#xff0c;然后chmod确保脚本文件具有可执行权限。这样脚本就可以在终端直…

从哪里下载高清解压视频素材?推荐五个优质素材资源网站

想制作吸引人的抖音小说推文&#xff0c;但不知道从哪里获取高清解压视频素材&#xff1f;今天就为大家推荐五个优秀的网站&#xff0c;帮助你轻松找到所需的素材&#xff0c;提升你的创作质量。 首先是蛙学网 作为国内顶级的短视频素材网站&#xff0c;蛙学网提供了丰富的4K高…

Vxe UI vue 使用 vxe-tabs 页签实现右侧操作按钮、关闭所有页签、关闭右侧、关闭左侧

Vxe UI vue 使用 vxe-tabs 页签实现右侧操作按钮、关闭所有页签、关闭右侧、关闭左侧 查看 github <template><div><vxe-tabs v-model"selectTab" :options"tabList"><template #extra><vxe-pulldown :options"tabOptio…

Flood Fill模型

这个模型主要用来求连通块的数量&#xff0c;在求连通块时有“8连通”和“4连通”之分。 看上面的图形&#xff0c;如果是4连通那么红色和绿色就不连通&#xff08;只有一个格子的“上下左右”相连才叫连通&#xff09;。如果是8连通那就联通&#xff08;不仅仅包含边相连&…

SwiftUI简明概念(4):如何对shape同时进行fill和stroke

1、iOS17方案 iOS17上可以同时对shape调用fill和stroke&#xff1a; Circle().stroke(.red, lineWidth: 20).fill(.orange).frame(width: 150, height: 150) 效果也如我们所预料的&#xff1a; 而且stroke可以调用任意次&#xff1a; Circle().stroke(.blue, lineWidth: 45…

【路径规划】基于球向量的粒子群优化(SPSO)算法在无人机路径规划中的实现

摘要 本文介绍了基于球形矢量的粒子群优化&#xff08;Spherical Particle Swarm Optimization, SPSO&#xff09;算法&#xff0c;用于无人机&#xff08;UAV&#xff09;路径规划。SPSO算法通过引入球形矢量的概念&#xff0c;增强了粒子群在多维空间中的探索和利用能力&…

TXT文档批量处理,根据总行数平均分成多个文件保存,批量拆分实例分享

在高强度的工作下&#xff0c;怎样拆分文档&#xff0c;手动拆分整理&#xff0c;不仅效率低&#xff0c;而且还容易出错。当然是要选择操作轻松简单首助编辑高手&#xff0c;提高工作效率。 1、打开软件并选择到文本批量操作功能选项上&#xff0c;选择文本批量操作&#xff1…

【C++】类和对象(类的定义,类域,实例化,this指针)

目录 一. 类的定义 【对比c】结构体和类的区别 1. 称呼&#xff1a;变量 or 对象&#xff1f; 2. 类型&#xff1a; 3. 访问限定&#xff1a; 4. c和c结构体使用 5. 相同点&#xff1a; 二. 类域 三. 实例化 1. 1对N 2. 计算大小只考虑成员变量 3. 到此一游 四. …

一、前后端分离及drf的概念

1.1什么是前后端分离 程序角度 前后端不分离&#xff1a;一个程序&#xff08;如django),接收请求处理HTML模版用户返回 前后端分离&#xff1a;两个程序 --前端&#xff1a;vue.js/react.js/angular.js --后端&#xff1a;Django drf(django rest framework) 2.专业角度 --…

3.消息机制总结——总结

Handler 机制的底层逻辑就是利用 epoll eventfdAndroid2.3开始 Google把Handler的阻塞/唤醒方案从Object#wait()/notify(),改为Linux epoll实现&#xff0c;why&#xff1f;原因在于&#xff0c;native也引入了消息管理机制&#xff0c;用于提供个C/C开发者使用&#xff0c;而…