用netty轻松实现一个高效稳定的TCP服务器
随着物联网的发展,很多项目都开始涉及到了tcp连接这块,在这里我们轻松用netty去实现,站在巨人的肩膀上。
关于netty包引用:
io.netty
netty-all
4.1.42.Final
compile
实现TCP服务器代码
依赖netty只需几行代码tcp服务:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteOrder;
public class TcpServer {
private Logger log = LoggerFactory.getLogger(getClass());
//自定义tcp服务端口号
private int port=9000;
static TcpServer tcpServer;
//单例设计模式
private TcpServer(){
}
public static TcpServer getInstance(){
if(tcpServer==null){
tcpServer=new TcpServer();
}
return tcpServer;
};
public void run() throws InterruptedException {
// 创建主线程组(接受连接)
EventLoopGroup bossGroup = new NioEventLoopGroup();
// 创建工作线程组(处理连接)
EventLoopGroup workerGroup = new NioEventLoopGroup(20); // 指定工作线程数量为20
// 创建ServerBootstrap实例,用于配置服务器
ServerBootstrap bootstrap = new ServerBootstrap();
// 配置主、工作线程组
bootstrap.group(bossGroup, workerGroup);
// 指定使用NIO进行网络传输
bootstrap.channel(NioServerSocketChannel.class);
// 设置子Channel的Socket选项,允许地址重用
bootstrap.childOption(ChannelOption.SO_REUSEADDR, true);
// 配置子Channel的处理器,这里使用ChannelInitializer
bootstrap.childHandler(new ChannelInitializer
() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
// 添加自定义的解码器,这里是处理协议
ch.pipeline().addLast(new YKCDecoderV1());
// 添加自定义的服务器处理器
ch.pipeline().addLast(new TCPServerHandler());
}
});
// 绑定端口并添加监听器,处理绑定操作的结果
bootstrap.bind(port).addListener((ChannelFutureListener) future -> {
// 在绑定成功后输出日志信息
log.info("bind success in port: " + port);
});
// 输出服务器启动成功信息
System.out.println("server started!");
}
}
业务处理代码(参考)
以下是处理报文业务类可参考,注意代码未优化:
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/
* 正则解析版
*/
public class YKCDecoderV1 extends ByteToMessageDecoder {
final static String reg = "^68.{14,332}";//单指令解析 根据业务协议报文定最短和最长
final static Pattern pattern1 = Pattern.compile(reg);
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf bufferIn, List