package com.tongran.agentserver.server.netty; import com.tongran.agentserver.server.netty.config.AgentNettyConfig; import com.tongran.agentserver.server.netty.handler.DecoderHandler; import com.tongran.agentserver.server.netty.handler.EncoderHandler; import com.tongran.agentserver.server.netty.handler.NettyClientHandler; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.timeout.IdleStateHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; @Component public class NettyTcpClient { private static final Logger logger = LoggerFactory.getLogger(NettyTcpClient.class); private EventLoopGroup group = new NioEventLoopGroup(); private Channel channel; @Resource private AgentNettyConfig config; // 目标服务器IP和端口 // private final String host = "www.tz2.xyz"; // 替换为实际IP // private final int port = 6610; // 替换为实际端口 /** * 启动客户端连接 */ @PostConstruct public void start() { try { connect(); } catch (Exception e) { logger.error("Netty客户端启动失败", e); } } public void connect() throws InterruptedException { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .handler(new ChannelInitializer() { @Override protected void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); // 添加编解码器 pipeline.addLast("decoder", new DecoderHandler()); pipeline.addLast("encoder", new EncoderHandler()); // 添加心跳机制 pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, 90, TimeUnit.SECONDS)); // 添加自定义处理器 pipeline.addLast("clientHandler", new NettyClientHandler()); } }); // 连接服务器 ChannelFuture future = bootstrap.connect(config.getHost(), config.getPort()).sync(); // 监听连接状态 future.addListener((ChannelFutureListener) f -> { if (f.isSuccess()) { logger.info("成功连接到TCP服务器 {}:{}", config.getHost(), config.getPort()); channel = f.channel(); } else { logger.error("连接TCP服务器失败 {}:{}, 5秒后尝试重连...", config.getHost(), config.getPort()); f.channel().eventLoop().schedule(() -> { try { connect(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }, 5, TimeUnit.SECONDS); } }); } /** * 发送消息 * @param message 要发送的消息内容 */ public void sendMessage(String message) { if (channel != null && channel.isActive()) { channel.writeAndFlush(message); logger.info("发送消息: {}", message); } else { logger.warn("TCP连接未建立,消息发送失败: {}", message); } } /** * 关闭连接 */ @PreDestroy public void stop() { if (channel != null) { channel.close(); } group.shutdownGracefully(); logger.info("Netty客户端已关闭"); } /** * 检查连接状态 * @return true表示连接正常 */ public boolean isConnected() { return channel != null && channel.isActive(); } }