package com.netty; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Syslog 服务器主类,支持 TCP 和 UDP 协议 */ public class SyslogServerBoth { private static final Logger logger = LoggerFactory.getLogger(SyslogServer.class); private final int tcpPort; private final int udpPort; // 共享的EventLoopGroup以优化资源使用 private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; private EventLoopGroup udpGroup; private ChannelFuture tcpChannelFuture; private ChannelFuture udpChannelFuture; private final ExecutorService serverExecutor = Executors.newFixedThreadPool(2); public SyslogServerBoth(int tcpPort, int udpPort) { this.tcpPort = tcpPort; this.udpPort = udpPort; } public void start() throws InterruptedException { logger.info("Starting Syslog server with TCP port {} and UDP port {}", tcpPort, udpPort); // 创建共享的EventLoopGroup bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(); udpGroup = new NioEventLoopGroup(); final CountDownLatch latch = new CountDownLatch(2); try { // 启动UDP服务器(使用独立的线程) serverExecutor.submit(() -> { try { startUdpServer(); latch.countDown(); } catch (Exception e) { logger.error("UDP server failed to start", e); latch.countDown(); throw new RuntimeException(e); } }); // 启动TCP服务器(使用独立的线程) serverExecutor.submit(() -> { try { startTcpServer(); latch.countDown(); } catch (Exception e) { logger.error("TCP server failed to start", e); latch.countDown(); throw new RuntimeException(e); } }); // 等待两个服务器都启动完成 latch.await(); logger.info("Both TCP and UDP Syslog servers are running"); // 注册关闭钩子 Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown)); // 保持主线程运行 Thread.currentThread().join(); } catch (Exception e) { logger.error("Failed to start servers", e); shutdown(); } } private void startTcpServer() throws InterruptedException { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new SyslogTcpChannelInitializer()) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); tcpChannelFuture = b.bind(tcpPort).sync(); logger.info("TCP Syslog server started on port {}", tcpPort); // 添加关闭监听器 tcpChannelFuture.channel().closeFuture().addListener(future -> { if (future.isSuccess()) { logger.info("TCP server channel closed"); } }); } private void startUdpServer() throws InterruptedException { Bootstrap b = new Bootstrap(); b.group(udpGroup) .channel(NioDatagramChannel.class) .handler(new SyslogUdpChannelInitializer()) .option(ChannelOption.SO_BROADCAST, true); udpChannelFuture = b.bind(udpPort).sync(); logger.info("UDP Syslog server started on port {}", udpPort); // 添加关闭监听器 udpChannelFuture.channel().closeFuture().addListener(future -> { if (future.isSuccess()) { logger.info("UDP server channel closed"); } }); } /** * 优雅关闭服务器 */ public void shutdown() { logger.info("Shutting down Syslog servers..."); try { // 关闭TCP服务器 if (tcpChannelFuture != null) { tcpChannelFuture.channel().close().sync(); } // 关闭UDP服务器 if (udpChannelFuture != null) { udpChannelFuture.channel().close().sync(); } // 关闭EventLoopGroup if (bossGroup != null) { bossGroup.shutdownGracefully().sync(); } if (workerGroup != null) { workerGroup.shutdownGracefully().sync(); } if (udpGroup != null) { udpGroup.shutdownGracefully().sync(); } // 关闭线程池 serverExecutor.shutdown(); logger.info("Syslog servers shutdown complete"); } catch (Exception e) { logger.error("Error during shutdown", e); } } /** * 检查服务器是否在运行 */ public boolean isRunning() { return (tcpChannelFuture != null && tcpChannelFuture.channel().isActive()) || (udpChannelFuture != null && udpChannelFuture.channel().isActive()); } public static void main(String[] args) throws Exception { int tcpPort = 514; int udpPort = 514; // 解析命令行参数 if (args.length >= 1) { tcpPort = Integer.parseInt(args[0]); } if (args.length >= 2) { udpPort = Integer.parseInt(args[1]); } // 如果两个端口相同,UDP端口自动+1避免冲突 if (tcpPort == udpPort) { udpPort = tcpPort + 1; logger.warn("TCP and UDP ports cannot be the same. UDP port changed to {}", udpPort); } SyslogServerBoth server = new SyslogServerBoth(tcpPort, udpPort); // 注册全局异常处理器 Thread.setDefaultUncaughtExceptionHandler((t, e) -> { logger.error("Uncaught exception in thread {}", t.getName(), e); }); server.start(); } }