代碼:
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 {/*** 在對象初始化后自動調用的方法,用于啟動服務器。* 無參數和返回值。*/@PostConstructpublic 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>() { // 設置通道初始化處理器@Overrideprotected 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>() { @Overrideprotected 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
,釋放資源。