java socket bio 改造为 netty nio
公司早些时候接入一款健康监测设备,由于业务原因近日把端口暴露在公网后,每当被恶意连接时系统会创建大量线程,在排查问题是发现是使用了厂家提供的服务端demo代码,在代码中使用的是java 原生socket,在发现连接后使用独立线程处理后续通信,占用系统资源造成了服务宕机,因此需要进行改造。
厂家提供的demo代码如下:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;public class Demo {public static void main(String[] args) {int port = 8003;if (args.length == 1) {port = Integer.parseInt(args[0]);}ServerSocket ss;try {ss = new ServerSocket(port);}catch (Exception e) {System.out.println("服务端socket失败 port = " + port);return;}System.out.println("启动socket监听 端口:" + port);List<Socket> socketList = new ArrayList<>();while (true) {try {Socket socket = ss.accept();if (socket == null || socket.isClosed()) {socketList.remove(socket);continue;}if (socketList.contains(socket)) {continue;}socketList.add(socket);System.out.println("socket连接 address = " + socket.getInetAddress().toString() + " port = " + socket.getPort());new Thread(new HealthReadThread(socket)).start();}catch (IOException e) {System.out.println(e.getMessage());}}}
}
import java.io.*;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;public class HealthReadThread implements Runnable {private Socket socket;HealthReadThread(Socket socket) {this.socket = socket;}private static String message = "";@Overridepublic void run() {try {//输入InputStream inPutStream = socket.getInputStream();BufferedInputStream bis = new BufferedInputStream(inPutStream);
// BufferedReader br = new BufferedReader(new InputStreamReader(inPutStream));//输出OutputStream outputStream = socket.getOutputStream();BufferedOutputStream bw = new BufferedOutputStream(outputStream);String ip = socket.getInetAddress().getHostAddress();int port = socket.getPort();String readStr = "";
// char[] buf;byte[] buf;int readLen = 0;while (true) {if (socket.isClosed()) {break;}buf = new byte[1024];try {readLen = bis.read(buf);if (readLen <= 0) {
// System.out.println(Thread.currentThread().getId() + "线程: " + "ip地址:" + ip + " 端口地址:" + port + "暂无接收数据");continue;}System.out.println(Thread.currentThread().getId() + "线程: " + "ip地址:" + ip + " 端口地址:" + port + " 接收到原始命令长度:" + readLen);readStr = StringUtils.byteToHexString(buf, readLen);
// readStr = new String(buf ,0 , readLen);} catch (IOException e) {System.out.println(e.getMessage());socket.close();
// continue;}if (readStr == null || "".equals(readStr)) {continue;}// 省略业务代码}}catch (Exception e) {System.out.println(e.getMessage());}}
}
使用netty进行改造:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
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.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class DeviceNettyServer implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {start();}public void start() {Thread thread = new Thread(() -> {// 配置服务端的NIO线程组EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup(4);ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup)// 使用 NIO 方式进行网络通信.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {// 添加自己的处理器ch.pipeline().addLast(new DeviceMsgHandler());}});try {int port1 = 8081;int port2 = 8082;// 绑定一个端口并且同步,生成一个ChannelFuture对象ChannelFuture f1 = b.bind(port1).sync();ChannelFuture f2 = b.bind(port2).sync();log.info("启动监听, 端口:" + port1 + "、" + port2);// 对关闭通道进行监听f1.channel().closeFuture().sync();f2.channel().closeFuture().sync();} catch (Exception e) {log.error("启动监听失败", e);} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}});thread.setName("DeviceNettyServer");thread.start();}
}
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;import java.util.*;
import java.util.concurrent.ConcurrentHashMap;@Slf4j
public class DeviceMsgHandler extends SimpleChannelInboundHandler<ByteBuf> {/*** 已连接的设备*/private static final ConcurrentHashMap<Channel, DeviceDTO> CONNECTION_DEVICE_MAP = new ConcurrentHashMap<>(8);/*** 一旦连接,第一个被执行*/@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {String remoteAddress = ctx.channel().remoteAddress().toString();log.info("发现连接, remoteAddress: " + remoteAddress);// 发送查询设备信息指令sendQuery(ctx.channel());}/*** 读取数据*/@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {byte[] bytes = new byte[msg.readableBytes()];msg.readBytes(bytes);// 忽略业务处理代码// 传递给下一个处理器ctx.fireChannelRead(msg);}/*** 连接断开** @param ctx*/@Overridepublic void handlerRemoved(ChannelHandlerContext ctx) {log.info("连接断开, remoteAddress: " + ctx.channel().remoteAddress());CONNECTION_DEVICE_MAP.remove(ctx.channel());}/*** 连接异常** @param ctx* @param cause*/@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {log.info("连接异常, remoteAddress: " + ctx.channel().remoteAddress());CONNECTION_DEVICE_MAP.remove(ctx.channel());}
经过改造后使用了4个worker线程进行读写,消除了原先恶意连接造成线程数无线扩大的问题,使用nio也极大的提高了系统资源利用率。
相关文章:
java socket bio 改造为 netty nio
公司早些时候接入一款健康监测设备,由于业务原因近日把端口暴露在公网后,每当被恶意连接时系统会创建大量线程,在排查问题是发现是使用了厂家提供的服务端demo代码,在代码中使用的是java 原生socket,在发现连接后使用独…...
进程、线程、协程详解:并发编程的三大武器
在现代计算机科学中,并发编程是一个核心概念,而进程、线程和协程是实现并发的三种主要方式。本文将深入探讨这三种概念,分析它们的特点、优缺点,以及适用场景。 1. 进程 (Process) 1.1 定义 进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的…...
探索5 大 Node.js 功能
目录 单线程 Node.js 工作线程【Worker Threads】 Node.js 进程 进程缺点 工作线程 注意 集群进程模块【Cluster Process Module】 内部发生了什么? 为什么要使用集群 注意: 应用场景: 内置 HTTP/2 支持 这个 HTTP/2 是什么&…...
EZUIKit.js萤石云vue项目使用
EZUIKit.js 是萤石云(Ezviz)提供的一款用于Web端的视频播放和控制的JavaScript库。它允许开发者在网页上轻松集成视频监控、对讲、录像回放等功能,适用于安防监控、智能家居等场景。通过EZUIKit.js,你可以方便地访问萤石云平台上的…...
【Linux】磁盘分区挂载网络配置进程【更详细,带实操】
Linux全套讲解系列,参考视频-B站韩顺平,本文的讲解更为详细 目录 一、磁盘分区挂载 1、磁盘分区机制 2、增加磁盘应用实例 3、磁盘情况查询 4、磁盘实用指令 二、网络配置 1、NAT网络原理图 2、网络配置指令 3、网络配置实例 4、主机名和host…...
Java 为什么使用 UTF-16 而不是更节省内存的 UTF-8?
Java 选择 UTF-16 编码而不是更节省内存的 UTF-8 这一决定,涉及多个层面的设计权衡,包括历史原因、虚拟机(JVM)实现的复杂度、性能和字符处理的一致性。要理解这个问题,我们需要从 Java 语言的设计初衷、JVM 的工作机制…...
损失函数篇 | YOLOv10 引入 Inner-IoU 基于辅助边框的IoU损失
作者导读:Inter-IoU:基于辅助边框的IoU损失 论文地址:https://arxiv.org/abs/2311.02877 作者视频解读:https://www.bilibili.com 开源代码地址:https://github.com/malagoutou/Inner-IoU...
夹耳开放式耳机好用吗?一篇文章告诉你答案,附上挑选避坑小知识
夹耳开放式耳机作为音频领域的新兴产品,正逐渐走入大众视野。其独特的设计和功能引发了广泛关注与讨论。究竟夹耳开放式耳机好用吗?在这篇文章中,我们将从专业角度深入剖析他的各个方面。同时,还会为你提供详细的挑选避坑小知识&a…...
WebSocket 2024/9/30
WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。 与HTTP协议的区别 实现...
大数据开发--1.1大数据概论
目录 一.大数据的概念 什么是大数据? 二. 大数据的特点 三. 大数据应用场景 四. 大数据分析业务步骤 大数据分析的业务流程: 五.大数据职业规划 职业方向 岗位技术要求 六. 大数据学习路线 一.大数据的概念 什么是大数据? 数据 世界…...
Java | Leetcode Java题解之第438题找到字符串中所有字母异位词
题目: 题解: class Solution {public List<Integer> findAnagrams(String s, String p) {int sLen s.length(), pLen p.length();if (sLen < pLen) {return new ArrayList<Integer>();}List<Integer> ans new ArrayList<Int…...
springboot整合MybatisPlus+MySQL
上一篇:springboot整合sentinel和对feign熔断降级 文章目录 一、准备二、主要工作三、具体步骤3.1 准备数据库环境3.20 pre引入依赖3.2 引入依赖3.3 bootstrap.yml配置mybatisplus3.40 pre引入service、mapper3.4 引入实体类、service、mapper 四、测试目录结构 五…...
【MySQL】视图、用户和权限管理
目录 视图创建视图数据修改影响删除视图视图优点 用户和权限管理查看当前的数据库拥有用户信息创建用户修改密码删除用户权限授权回收权限 视图 视图就是相当于创建一个表,将查询到的结果集给存储起来。像使用复杂的多表查询查询到的结果集就不可以对结果集操作。而…...
Linux基础(五):linux文件种类与扩展名
1.文件种类 文件种类含义正规文件( regular file )就是一般我们在进行存取的类型的文件, 在由 ls -al 所显示出来的属性方面, 第一个字符为 [ - ], 例如 [-rwxrwxrwx ]。 另外, 依照文件的内容,…...
C语言-c语言组成
1.C语言的组成 一个C源程序是由 一个或者多个.c文件 和 0个或者多个.h 文件 组成 源程序: 是指未编译的 按照一定的程序设计语言规范书写的文本文件 .c文件 : c源代码 .h文件 : 头文件(接口文件) 2. .c文件 1)预处理命令 以#开头的行,在编译之前 会事…...
编程题 7-13 日K蜡烛图【PAT】
文章目录 题目输入格式输出格式输入样例1输出样例1输入样例2输出样例2输入样例3输出样例3 题解解题思路完整代码 编程练习题目集目录 题目 股票价格涨跌趋势,常用蜡烛图技术中的 K K K 线图来表示,分为按日的日 K K K 线、按周的周 K K K 线、按月的…...
iOS开发工程师面试
iOS开发工程师面试题可以涵盖多个方面,包括但不限于iOS开发的基础知识、高级概念、性能优化、架构设计、最新技术等。 1. 基础知识 1.1 请解释iOS中的Xcode是什么,以及它在开发中的作用和功能有哪些? Xcode是用于iOS和macOS等苹果平台开发的集成开发环境(IDE),提供了代…...
无人机避障—— 激光雷达定高北醒TF03-UART(二)
无人机避障过程,光靠大疆飞控内部的气压计不准,很容易在高度较低的时候受到地面植被等障碍物影响,使得掉高严重,因此采用激光雷达定高模块进行定高。 硬件: 北醒TF03-UART、Xavier-NX 软件代码: 北醒官…...
在虚幻引擎中实现Camera Shake 相机抖动/震屏效果
在虚幻引擎游戏中创建相机抖动有时能让画面更加高级 , 比如 遇到大型的Boss , 出现一些炫酷的特效 加一些短而快的 Camera Shake 能达到很好的效果 , 为玩家提供沉浸感 创建Camera Shake 调整Shake参数 到第三人称或第一人称蓝图 调用Camera Shake Radius值越大 晃动越强...
SQL Server的文本和图像函数
新书速览|SQL Server 2022从入门到精通:视频教学超值版_sql server 2022 出版社-CSDN博客 《SQL Server 2022从入门到精通(视频教学超值版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) SQL Se…...
火狐浏览器必备:Z-Library Finder扩展安装与使用全攻略(附最新下载链接)
火狐浏览器高效获取电子书资源:Z-Library Finder扩展深度指南 在数字阅读日益普及的今天,电子书资源获取工具成为许多阅读爱好者的刚需。对于火狐浏览器用户而言,Z-Library Finder扩展无疑是一款能够极大提升电子书搜索效率的神器。这款工具专…...
最近帮实验室刚入门的师弟复现了西储大学轴承故障的迁移学习代码,本来以为是手到擒来的活,结果还是踩了好几个坑,刚好整理出来给同样摸鱼入门的小伙伴参考
一区top轴承故障诊断迁移学习代码复现 故障诊断代码 复现首先使用一维的cnn对源域和目标域进行特征提取,域适应阶段:将源域和目标域作为cnn的输入得到特征,然后进行边缘概率分布对齐和条件概率分布对齐,也就是进行JDA联合对齐。此…...
情感GDP报告:测试员负面情绪成经济指标的行业变革
一、导言:情感GDP的崛起与测试行业新坐标 2025年全球情感计算市场规模突破596亿元(数据来源:2024年情感计算行业报告),"情感GDP"作为衡量情绪价值的经济指标,正重塑职业评价体系。软件测试领域首…...
基于.NET 11 与C# 14的高性能安全客户端应用开发
基于.NET 11 与C# 14的高性能安全客户端应用开发 前言 在客户端应用开发领域,性能与安全始终是关键指标。随着.NET 11 和 C# 14 的推出,开发者拥有了更强大的工具来构建高性能且安全可靠的客户端应用。这些新技术不仅提升了应用的运行效率,还…...
Path of Building完全指南:精准规划角色构筑3步法+高效配置策略
Path of Building完全指南:精准规划角色构筑3步法高效配置策略 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/gh_mirrors/pat/PathOfBuilding Path of Building是一款强大的离线工具,…...
终极Windows文件完整性验证指南:为什么专业开发者都选择HashCheck Shell Extension
终极Windows文件完整性验证指南:为什么专业开发者都选择HashCheck Shell Extension 【免费下载链接】HashCheck HashCheck Shell Extension for Windows with added SHA2, SHA3, and multithreading; originally from code.kliu.org 项目地址: https://gitcode.co…...
Python开发环境快速搭建:Miniconda-Python3.9镜像实战体验
Python开发环境快速搭建:Miniconda-Python3.9镜像实战体验 1. 为什么选择Miniconda-Python3.9 Python作为当今最流行的编程语言之一,在数据科学、机器学习、Web开发等领域有着广泛应用。然而,Python环境管理一直是开发者面临的挑战之一。Mi…...
从热电偶到串口显示:用STM32F103C8T6+MAX6675搭建简易温度监控系统
从零搭建热电偶温度监控系统:STM32F103C8T6与MAX6675实战指南 在工业测量和创客项目中,温度监控是最基础却至关重要的环节。想象一下,当你需要精确控制3D打印机的热床温度、监测烘焙设备的加热曲线,或是记录温室大棚的环境变化时&…...
axure-cn语言包:让Axure RP全版本界面无缝切换至中文的完整指南
axure-cn语言包:让Axure RP全版本界面无缝切换至中文的完整指南 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包,不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-…...
ARM A53上跑通1080P实时EIS防抖?手把手教你优化特征点与透视变换(附代码思路)
ARM A53实战:1080P实时EIS防抖的7个关键优化策略 当行车记录仪的镜头在颠簸路面剧烈晃动,或是运动相机在冲浪时被海浪拍打,画面稳定性的价值就凸显出来。传统光学防抖受限于物理结构,而电子防抖(EIS)通过算法补偿成为嵌入式设备的…...
