netty版本
- netty版本:
io.netty:netty-all:4.1.33.Final
服务端多端口绑定
-
服务端单进程多端口绑定,如果要停止某一个端口的监听,一定不能停止EventLoop和Accept线程,单独关闭某一个
Channel
即可。package cn.jannal.netty; /** * 使用telnet 127.0.0.1 6000 测试 */ public final class Server { private EventLoopGroup bossGroup = new NioEventLoopGroup(); private EventLoopGroup workerGroup = new NioEventLoopGroup(); private ServerBootstrap bootstrap = new ServerBootstrap(); private ChannelFuture[] ChannelFutures = null; private int beginPort = 0; private int endPort = 0; public Server(int beginPort, int endPort) { this.beginPort = beginPort; this.endPort = endPort; } public static void main(String[] args) { Server server = new Server(6000, 8000); server.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { } server.stopServerChannel(6000); } public void start() { System.out.println("server starting...."); bootstrap.group(bossGroup, workerGroup); bootstrap.channel(NioServerSocketChannel.class); bootstrap.childOption(ChannelOption.SO_REUSEADDR, true); bootstrap.childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new CountHandler()); } }); if (ChannelFutures == null) { ChannelFutures = new ChannelFuture[endPort - beginPort + 1]; } //多个端口绑定 for (int i = beginPort; i <= endPort; i++) { final int port = i; ChannelFuture channelFuture = bootstrap.bind(port); ChannelFutures[i - beginPort] = channelFuture; channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(Future<? super Void> future) throws Exception { if (future.isSuccess()) { System.out.println("Started success,port:" + port); } else { System.out.println("Started Failed,port:" + port); } } }); } for (int i = 0; i <= endPort - beginPort; i++) { final Channel channel = ChannelFutures[i].channel(); int index = i; channel.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(Future<? super Void> future) { System.out.println("channel close !"); channel.close(); ChannelFutures[index] = null; } }); } } public void stopAll() { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); System.out.println("stoped"); } //关闭单个端口的NioServerSocketChannel public void stopServerChannel(int port) { int i = port - beginPort; if (0 <= i && i <= ChannelFutures.length) { if (ChannelFutures != null) { ChannelFutures[i].channel().close(); } System.out.println("stoped " + port); } } } @ChannelHandler.Sharable class CountHandler extends ChannelInboundHandlerAdapter { private AtomicInteger nConnection = new AtomicInteger(); public CountHandler() { Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> { System.out.println("connections: " + nConnection.get()); }, 0, 2, TimeUnit.SECONDS); } @Override public void channelActive(ChannelHandlerContext ctx) { nConnection.incrementAndGet(); } @Override public void channelInactive(ChannelHandlerContext ctx) { nConnection.decrementAndGet(); } }
客户端连接多个服务端端口
-
客户端连接多个服务端端口
public class Client { private EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); private Bootstrap bootstrap = new Bootstrap(); private int startPort; private int endPort; private String serverHost; private ChannelFuture[] ChannelFutures = null; public Client(int startPort, int endPort, String serverHost) { this.startPort = startPort; this.endPort = endPort; this.serverHost = serverHost; } public static void main(String[] args) throws Exception { Client client = new Client(6000, 8000, "127.0.0.1"); client.start(); } public void start() throws Exception { bootstrap.group(eventLoopGroup); bootstrap.channel(NioSocketChannel.class); bootstrap.option(ChannelOption.SO_REUSEADDR, true); bootstrap.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new ClientHandler()); } }); if (ChannelFutures == null) { ChannelFutures = new ChannelFuture[endPort - startPort + 1]; } //同时连接多个端口 for (int i = startPort; i <= endPort; i++) { ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress(serverHost,i)); int port = i; ChannelFutures[i - startPort] = channelFuture; channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(Future<? super Void> future) throws Exception { if (future.isSuccess()) { System.out.println("connect success port : " + port); } else { System.out.println("connect failed port : " + port); } } }); Channel channel = channelFuture.channel(); channel.closeFuture().addListener(new GenericFutureListener<Future<? super Void>>() { @Override public void operationComplete(Future<? super Void> future) throws Exception { channel.close(); } }); } } public void stop(){ eventLoopGroup.shutdownGracefully(); System.out.println("stop"); } public void closeChannel(int port) { int i = port - startPort; if (0 <= i && i <= ChannelFutures.length) { if (ChannelFutures != null) { ChannelFutures[i].channel().close(); } System.out.println("stoped " + port); } } } class ClientHandler extends SimpleChannelInboundHandler<String> { @Override public void channelActive(ChannelHandlerContext ctx) { ctx.writeAndFlush(Unpooled.copiedBuffer("echo server!\n", CharsetUtil.UTF_8)); } //用十六进制记录接收到的消息 @Override public void channelRead0(ChannelHandlerContext ctx, String in) { System.out.println(in); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }