代码:
javascript
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方法。在该方法中,向通道的处理链中添加了StringDecoder、StringEncoder和DeviceDataHandler。StringDecoder用于将接收到的字节数据解码为字符串,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,释放资源。