基于 Netty 框架的 Java TCP 服务器端实现,用于启动一个 TCP 服务器来处理客户端的连接和数据传输

news2025/4/6 7:15:16

代码:

package com.example.tpson_tcp;
 
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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 io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Service;
 
import javax.annotation.PostConstruct;
 
/**
 * Netty服务端类,用于启动TCP服务器。
 */
@Service
public class NettyServer {
 
    /**
     * 在对象初始化后自动调用的方法,用于启动服务器。
     * 无参数和返回值。
     */
    @PostConstruct
    public void main() {
        // 创建EventLoopGroup用于处理网络事件
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 配置服务器启动参数
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // 指定使用的NIO通道类
                    .childHandler(new ChannelInitializer<SocketChannel>() { // 设置通道初始化处理器
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            // 在通道中添加处理链,用于解码、编码和处理设备数据
                            ch.pipeline().addLast(new StringDecoder());
                            ch.pipeline().addLast(new StringEncoder());
                            ch.pipeline().addLast(new DeviceDataHandler());
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128) // 设置连接队列大小
                    .childOption(ChannelOption.SO_KEEPALIVE, true); // 启用TCP KeepAlive
 
            // 绑定端口并启动服务器
            ChannelFuture channelFuture = serverBootstrap.bind(8092).sync();
            // 等待服务器关闭
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            // 异常处理,抛出运行时异常
            throw new RuntimeException(e);
        } finally {
            // 关闭EventLoopGroup,释放资源
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
}

代码解释:

1. 包导入部分

java

package com.example.tpson_tcp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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 io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
  • package com.example.tpson_tcp;:指定该类所属的包名。
  • 后续一系列 import 语句引入了 Netty 框架的相关类,用于网络编程。ServerBootstrap 用于配置和启动服务器;EventLoopGroup 是用于处理网络事件的线程池;StringDecoder 和 StringEncoder 用于对字符串进行编解码。
  • org.springframework.stereotype.Service 表明这是一个 Spring 服务类。
  • javax.annotation.PostConstruct 用于标记一个方法,该方法会在对象初始化后自动调用。

2. 类定义和注解

java

  • @Service:这是 Spring 框架的注解,将 NettyServer 类标记为一个服务组件,Spring 会自动扫描并管理这个类的实例。
  • public class NettyServer:定义了一个名为 NettyServer 的公共类。

3. main 方法

java

@PostConstruct
public void main() {
  • @PostConstruct:该注解表明 main 方法会在 NettyServer 类的实例被创建并初始化后自动调用。
  • public void main():定义了一个公共的无返回值方法 main

4. 创建 EventLoopGroup

java

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

  • NioEventLoopGroup 是 Netty 提供的基于 Java NIO 的事件循环组,用于处理网络事件。
  • bossGroup 主要负责接受客户端的连接请求。
  • workerGroup 负责处理已经建立的连接的读写操作。

5. 配置服务器启动参数

java

ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class) 
        .childHandler(new ChannelInitializer<SocketChannel>() { 
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                ch.pipeline().addLast(new StringDecoder());
                ch.pipeline().addLast(new StringEncoder());
                ch.pipeline().addLast(new DeviceDataHandler());
            }
        })
        .option(ChannelOption.SO_BACKLOG, 128) 
        .childOption(ChannelOption.SO_KEEPALIVE, true); 

  • ServerBootstrap 用于配置和启动服务器。
  • group(bossGroup, workerGroup):指定使用的 EventLoopGroup
  • channel(NioServerSocketChannel.class):指定使用的 NIO 通道类,用于接受客户端的连接。
  • childHandler:设置通道初始化处理器,当有新的连接建立时,会调用 initChannel 方法。在该方法中,向通道的处理链中添加了 StringDecoderStringEncoder 和 DeviceDataHandlerStringDecoder 用于将接收到的字节数据解码为字符串,StringEncoder 用于将字符串编码为字节数据发送出去,DeviceDataHandler 用于处理具体的业务逻辑。
  • option(ChannelOption.SO_BACKLOG, 128):设置连接队列的大小,即允许等待处理的最大连接数。
  • childOption(ChannelOption.SO_KEEPALIVE, true):启用 TCP 的 KeepAlive 机制,用于检测长时间空闲的连接是否仍然有效。

6. 绑定端口并启动服务器

java

ChannelFuture channelFuture = serverBootstrap.bind(8092).sync();
channelFuture.channel().closeFuture().sync();
  • serverBootstrap.bind(8092):将服务器绑定到指定的端口 8092。
  • sync() 方法是一个同步方法,会阻塞当前线程,直到绑定操作完成。
  • channelFuture.channel().closeFuture().sync():等待服务器关闭,会阻塞当前线程,直到服务器的通道关闭。

7. 异常处理和资源释放

java

} catch (InterruptedException e) {
    throw new RuntimeException(e);
} finally {
    workerGroup.shutdownGracefully();
    bossGroup.shutdownGracefully();
}
  • catch (InterruptedException e):捕获 InterruptedException 异常,当线程在等待过程中被中断时会抛出该异常,将其包装成 RuntimeException 重新抛出。
  • finally 块:无论是否发生异常,都会执行该块中的代码,调用 shutdownGracefully() 方法来优雅地关闭 workerGroup 和 bossGroup,释放资源。

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

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

相关文章

OFP--2018

文章目录 AbstractIntroductionRelated Work2D object detection3D object detection from LiDAR3D object detection from imagesIntegral images 3D Object Detection ArchitectureFeature extractionOrthographic feature transformFast average pooling with integral imag…

CentOS-查询实时报错日志-查询前1天业务报错gz压缩日志

最新版本更新 https://code.jiangjiesheng.cn/article/364?fromcsdn 推荐 《高并发 & 微服务 & 性能调优实战案例100讲 源码下载》 1. 查询实时报错日志 物理路径&#xff08;带*的放在靠后&#xff0c;或者不用*&#xff09; cd /home/logs/java-gz-log-dir &am…

ETF 场内基金是什么?佣金最低又是多少呢?

嘿&#xff0c;朋友们&#xff0c;大家好啊&#xff0c;我是StockMasterX&#xff0c;今天咱们就坐下来慢慢聊聊这个话题&#xff0c;ETF 场内基金到底是个啥东西&#xff0c;它的佣金最低能到多少&#xff0c;真的是个值得深挖的问题。 说起ETF&#xff0c;我还记得刚入行那会…

[论文阅读]PMC-LLaMA: Towards Building Open-source Language Models for Medicine

PMC-LLaMA&#xff1a;构建医学开源语言模型 摘要 最近&#xff0c;大语言模型在自然语言理解方面展现了非凡的能力。尽管在日常交流和问答场景下表现很好&#xff0c;但是由于缺乏特定领域的知识&#xff0c;这些模型在需要精确度的领域经常表现不佳&#xff0c;例如医学应用…

26考研——线性表(2)

408答疑 文章目录 一、线性表的定义和基本操作二、线性表的顺序表示三、 线性表的链式表示四、 顺序表和链表的比较五、参考资料鲍鱼科技课件26王道考研书 六、总结顺序表总结顺序表特点深入掌握顺序表的管理方式 单链表总结双循环链表总结 一、线性表的定义和基本操作 文章链…

低代码开发平台:飞帆画 echarts 柱状图

https://fvi.cn/711 柱状图这个控件是由折线图的控件改过来的&#xff0c;在配置中&#xff0c;单选框选择柱状图就行了。

PowerPhotos:拯救你的Mac照片库,告别苹果原生应用的局限

如果你用Mac管理照片&#xff0c;大概率被苹果原生「照片」应用折磨过——无法真正并行操作多个图库。每次切换图库都要关闭重启&#xff0c;想合并照片得手动导出导入&#xff0c;重复文件更是无处可逃…… 直到我发现了 PowerPhotos&#xff0c;这款专为Mac设计的照片库管理…

Linux 下 日志系统搭建全攻略

目录 一、引言 二、日志系统基础 日志级别 日志输出格式 三、创建日志所需函数 认识可变参数 ​编辑 获取时间的函数 小结 四、创建日志 一、引言 在 Linux 环境中开发 C/C 程序时&#xff0c;日志系统是不可或缺的一部分。它不仅有助于调试程序、排查问题&#xff…

Linux系统安装Postgre和Postgis教程

卸载 如果之前没装过可以忽略这一步 卸载前记得备份数据库数据(如果还需要的话)&#xff01;&#xff01;&#xff01; 一、删除 Docker 安装的 PostgreSQL/PostGIS 1. 停止并删除容器 # 查看所有容器 docker ps -a | grep postgres# 停止并删除容器&#xff08;替换为实际…

LXC 导入多Linux系统

前提要求 ubuntu下安装lxd 参考Rockylinux下安装lxd 参考LXC 源替换参考LXC 容器端口发布参考LXC webui 管理<

6547网:蓝桥STEMA考试 Scratch 试卷(2025年3月)

『STEMA考试是蓝桥青少教育理念的一部分&#xff0c;旨在培养学生的知识广度和独立思考能力。考试内容主要考察学生的未来STEM素养、计算思维能力和创意编程实践能力。』 一、选择题 第一题 运行下列哪个程序后&#xff0c;飞机会向左移动&#xff1f; ( ) A. …

使用Webpack搭建React项目:从零开始

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

STM32提高篇: CAN通讯

STM32提高篇: CAN通讯 一.CAN通讯介绍1.物理层2.协议层二.STM32CAN外设1.CAN控制器的3种工作模式2.CAN控制器的3种测试模式3.功能框图三.CAN的寄存器介绍1.环回静默模式测试2.双击互发测试四.CAN的HAL代码解读一.CAN通讯介绍 CAN(Controller Area Network 控制器局域网,简称…

25.Reactor

预备知识 std::bind template <class Fn, class... Args>/* unspecified */ bind (Fn&& fn, Args&&... args);解释&#xff1a; std::bind(&TcpServer::Accepter, this, std::placeholders::_1) 这段代码使用了 C11 中的 std::bind 函数&#xff0…

Linux进程间通信——有名管道

一.概念 函数形式&#xff1a;int mkfifo(const char \*filename,mode_t mode); 功能&#xff1a;创建管道文件 参数&#xff1a;管道文件文件名\路径&#xff0c;权限&#xff0c;创建的文件权限仍然和umask有关系。 返回值&#xff1a;创建成功返回0&#xff0c;创建失败返回…

Axure RP9.0教程: 查询条件隐藏与显示(综合了动态面板状态切换及展开收缩效果实现)

文章目录 引言I 原型显示/隐藏搜索框思路步骤详细操作II 若依 ruoyi 显示/隐藏搜索框 & 显示隐藏列自定义设置显示隐藏列显示/隐藏搜索框引言 数据筛选有大量的查询条件时,可以选择查询隐藏效果。 I 原型显示/隐藏搜索框 综合了动态面板状态切换及展开收缩效果实现 思…

【漫话机器学习系列】183.非参数方法(Non-parametric Methods)

非参数方法&#xff08;Non-parametric Methods&#xff09;详解 概述 非参数方法是一类在统计学和机器学习中广泛应用的技术&#xff0c;它的特点是不对特征值和目标值之间的关系做具体的假设。与传统的参数方法&#xff08;如线性回归、逻辑回归等&#xff09;不同&#xf…

智能驾驶中预测模块简介

1.轨迹预测的定义 轨迹预测是自动驾驶系统“感知-预测-规控”流程中的核心环节&#xff0c;位于感知与规划模块之间&#xff0c;起到承上启下的作用。感知系统负责检测道路环境中的动态和静态元素&#xff0c;包括车辆、行人、自行车、交通标志、车道线等&#xff0c;而预测模…

剑指offer经典题型(一)

本期我们将开始进行剑指offer中经典题型的学习。 数组相关 题目1&#xff1a;在一个二维数组中&#xff08;每个一维数组的长度相同&#xff09;&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输…

ctfshow VIP题目限免 版本控制泄露源码2

根据题目提示是版本控制泄露源码 版本控制&#xff08;Version Control&#xff09;是一种在软件开发和其他领域中广泛使用的技术&#xff0c;用于管理文件或项目的变更历史。 主流的版本控制工具&#xff1a; ‌Git‌&#xff1a;目前最流行的分布式版本控制系统。‌SVN‌&am…