Article directory
- 1. Introduction
- 2. Code implementation
-
- 2.1 Engineering structure
- 2.2 Netty client
-
- 2.2.1 Client Processor
- 2.2.2 Client channel initialization
- 2.2.3 Client channel listener
- 2.2.4 Client
- 2.3 Netty server
-
- 2.3.1 Server-side processor
- 2.3.2 Server channel initialization
- 2.3.3 Server
- 3. Unit testing
1. Introduction
When using Netty, it is necessary to monitor whether the service is stable and to automatically reconnect when the network link is disconnected due to abnormal network conditions.
Need to listen:f.addListener(new MyChannelFutureListener())
2. Code implementation
2.1 Project Structure
netty-2.0-08 |-src |-main |-java |-com.lino.netty |-client | |-MyChannelFutureListener.java | |-MyChannelInitializer.java | |-MyClientHandler.java | |-NettyClient.java |-server | |-MyChannelInitializer.java | |-MyServerHandler.java | |-NettyServer.java
2.2 Netty client
2.2.1 Client Processor
MyClientHandler.java
package com.lino.netty.client; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.socket.SocketChannel; import java.time.LocalDateTime; /** * @description: client processor */ public class MyClientHandler extends ChannelInboundHandlerAdapter {<!-- --> /** * When the client actively connects to the server's connection, this channel is active. That is, the client and server have established a communication channel and can transmit data. */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception {<!-- --> SocketChannel channel = (SocketChannel) ctx.channel(); System.out.println("Link report starts"); System.out.println("Link report information: This client is connected to the server. channelId: " + channel.id()); System.out.println("Link reporting IP:" + channel.localAddress().getHostString()); System.out.println("Link report Port:" + channel.localAddress().getPort()); System.out.println("Link report completed"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception {<!-- --> System.out.println("Disconnect and reconnect" + ctx.channel().localAddress().toString()); // Use process interrupt line to reconnect new Thread(new Runnable() {<!-- --> @Override public void run() {<!-- --> try {<!-- --> new NettyClient().connect("127.0.0.1", 7397); System.out.println("lino-learn-netty client start done."); Thread.sleep(500); } catch (Exception e) {<!-- --> System.out.println("lino-learn-netty client start error go reconnect."); } } }).start(); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {<!-- --> //Receive msg message System.out.println(LocalDateTime.now() + "Message received: " + msg); } /** * Catch exceptions. When an exception occurs, you can do some corresponding processing, such as printing logs and closing links. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {<!-- --> System.out.println("Exception message, disconnect and reconnect:\r\ " + cause.getMessage()); ctx.close(); } }
2.2.2 Client channel initialization
MyChannelInitializer.java
package com.lino.netty.client; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import java.nio.charset.Charset; /** * @description: Client channel initialization */ public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {<!-- --> @Override protected void initChannel(SocketChannel channel) throws Exception {<!-- --> // Convert encoding to String, pay attention to adjusting your own encoding format GBK, UTF-8 channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK"))); // Decode to String, pay attention to adjust your own encoding format GBK, UTF-8 channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK"))); //Add yourself to the receiving data implementation method in the pipeline channel.pipeline().addLast(new MyClientHandler()); } }
2.2.3 Client Channel Listener
MyChannelFutureListener.java
package com.lino.netty.client; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.EventLoop; import java.util.concurrent.TimeUnit; /** * @description: Channel listener */ public class MyChannelFutureListener implements ChannelFutureListener {<!-- --> @Override public void operationComplete(ChannelFuture channelFuture) throws Exception {<!-- --> if (channelFuture.isSuccess()) {<!-- --> System.out.println("lino-learn-netty client start done."); return; } final EventLoop loop = channelFuture.channel().eventLoop(); loop.schedule(new Runnable() {<!-- --> @Override public void run() {<!-- --> try {<!-- --> new NettyClient().connect("127.0.0.1", 7397); System.out.println("lino-learn-netty client start done."); Thread.sleep(500); } catch (Exception e) {<!-- --> System.out.println("lino-learn-netty client start error go reconnect."); } } }, 1L, TimeUnit.SECONDS); } }
2.2.4 Client
NettyClient.java
package com.lino.netty.client; import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; /** * @description: client */ public class NettyClient {<!-- --> public static void main(String[] args) {<!-- --> new NettyClient().connect("127.0.0.1", 7397); } public void connect(String inetHost, int inetPort) {<!-- --> EventLoopGroup workerGroup = new NioEventLoopGroup(); try {<!-- --> Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.AUTO_READ, true); b.handler(new MyChannelInitializer()); ChannelFuture f = b.connect(inetHost, inetPort).sync(); //Add monitoring and handle reconnection f.addListener(new MyChannelFutureListener()); f.channel().closeFuture().sync(); } catch (InterruptedException e) {<!-- --> e.printStackTrace(); } finally {<!-- --> workerGroup.shutdownGracefully(); } } }
2.3 Netty server
2.3.1 Server-side processor
MyServerHandler.java
package com.lino.netty.server; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.socket.SocketChannel; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; import java.time.LocalDateTime; import java.util.Date; /** * @description: Server-side processor */ public class MyServerHandler extends ChannelInboundHandlerAdapter {<!-- --> @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {<!-- --> super.userEventTriggered(ctx, evt); if (evt instanceof IdleStateEvent) {<!-- --> IdleStateEvent e = (IdleStateEvent) evt; if (e.state() == IdleState.READER_IDLE) {<!-- --> System.out.println("Reminder => Reader Idle"); ctx.writeAndFlush("Reading waiting: Are you there, client? [ctx.close()]{I end with a newline character for processing half-packed sticky packets}... ...\ "); ctx.close(); } else if (e.state() == IdleState.WRITER_IDLE) {<!-- --> System.out.println("Reminder => Writer Idle"); ctx.writeAndFlush("Write waiting: Client are you there {I end with a newline character for processing half-packet sticky packets}... ...\ "); } else if (e.state() == IdleState.ALL_IDLE) {<!-- --> System.out.println("Reminder => All Idle"); ctx.writeAndFlush("All time: Client are you there {I end with a newline character for processing half-packet sticky packets}... ...\ "); } } ctx.flush(); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception {<!-- --> SocketChannel channel = (SocketChannel) ctx.channel(); System.out.println("Link report starts"); System.out.println("Link report information: There is a client connected to this server. channelId: " + channel.id()); System.out.println("Link reporting IP:" + channel.localAddress().getHostString()); System.out.println("Link report Port:" + channel.localAddress().getPort()); System.out.println("Link report completed"); //Notify the client that the connection is successfully established String str = "Notify the client that the link is established successfully" + " " + new Date() + " " + channel.localAddress().getHostString() + "\r\ "; ctx.writeAndFlush(str); } /** * When the client actively disconnects from the server, this channel is inactive. * That is to say, the communication channel between the client and the server is closed and data cannot be transmitted. */ @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception {<!-- --> System.out.println("Client disconnected" + ctx.channel().localAddress().toString()); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {<!-- --> //Receive msg message System.out.println(LocalDateTime.now() + "Message received: " + msg); //Notify the client that the link message is sent successfully String str = "The server received: " + new Date() + " " + msg + "\r\ "; ctx.writeAndFlush(str); } /** * Catch exceptions. When an exception occurs, you can do some corresponding processing, such as printing logs and closing links. */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {<!-- --> System.out.println("Exception message:\r\ " + cause.getMessage()); ctx.close(); } }
2.3.2 Server channel initialization
MyChannelInitializer.java
package com.lino.netty.server; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.IdleStateHandler; import java.nio.charset.Charset; /** * @description: Server channel initialization */ public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {<!-- --> @Override protected void initChannel(SocketChannel channel) {<!-- --> /** * Heartbeat detection * 1. readerIdleTimeSeconds read timeout * 2. writerIdleTimeSeconds write timeout time * 3. allIdleTimeSeconds read and write timeout * 4. TimeUnit.SECONDS seconds [default is seconds, can be specified] */ channel.pipeline().addLast(new IdleStateHandler(2, 2, 2)); // Convert encoding to String, pay attention to adjusting your own encoding format GBK, UTF-8 channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK"))); // Decode to String, pay attention to adjust your own encoding format GBK, UTF-8 channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK"))); //Add yourself to the receiving data implementation method in the pipeline channel.pipeline().addLast(new MyServerHandler()); } }
2.3.3 Server
NettyServer.java
package com.lino.netty.server; 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.NioServerSocketChannel; /** * @description: netty server */ public class NettyServer {<!-- --> public static void main(String[] args) {<!-- --> new NettyServer().bind(7397); } public void bind(int port) {<!-- --> EventLoopGroup parentGroup = new NioEventLoopGroup(); EventLoopGroup childGroup = new NioEventLoopGroup(); try {<!-- --> ServerBootstrap b = new ServerBootstrap(); b.group(parentGroup, childGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childHandler(new MyChannelInitializer()); ChannelFuture f = b.bind(port).sync(); System.out.println("lino-learn-netty server start done."); f.channel().closeFuture().sync(); } catch (InterruptedException e) {<!-- --> e.printStackTrace(); } finally {<!-- --> childGroup.shutdownGracefully(); parentGroup.shutdownGracefully(); } } }
3. Unit testing
Start the NettyServer server
lino-learn-netty server start done. Link report starts Link report information: There is a client connected to this server. channelId: 04a06009 Link reporting IP: 127.0.0.1 Link Report Port: 7397 Link report completed Reminder => Reader Idle Client disconnected/127.0.0.1:7397 Link report starts Link report information: There is a client connected to this server. channelId: 0f99d6d1 Link reporting IP: 127.0.0.1 Link Report Port: 7397 Link report completed Reminder => Reader Idle Client disconnected/127.0.0.1:7397 Link report starts Link report information: There is a client connected to this server. channelId:ebbe72d6 Link reporting IP: 127.0.0.1 Link Report Port: 7397 Link report completed Reminder => Reader Idle Client disconnected/127.0.0.1:7397 Link report starts Link report information: There is a client connected to this server. channelId: 179882e0 Link reporting IP: 127.0.0.1 Link Report Port: 7397 Link report completed Exception information: The remote host forcibly closed an existing connection. Client disconnected/127.0.0.1:7397
Start the Netty client
Link report starts Link report information: This client is linked to the server. channelId: 72cce3a8 Link reporting IP: 127.0.0.1 Link report Port: 63858 Link report completed lino-learn-netty client start done. 2023-02-28T16:26:19.131 Message received: Notify the client that the link was successfully established Tue Feb 28 16:26:19 CST 2023 127.0.0.1 2023-02-28T16:26:21.092 Message received: Read waiting: Client are you there [ctx.close()]{<!-- -->I end with a newline character for processing half-package sticky packages }... ... Disconnect and reconnect/127.0.0.1:63858 Link report starts Link report information: This client is linked to the server. channelId: 1864a134 Link reporting IP: 127.0.0.1 Link Report Port: 63893 Link report completed lino-learn-netty client start done. 2023-02-28T16:26:21.103 Message received: Notify the client that the link was successfully established Tue Feb 28 16:26:21 CST 2023 127.0.0.1 2023-02-28T16:26:23.119 Message received: Read waiting: Client, are you there [ctx.close()]{<!-- -->I end with a newline character for processing half-package sticky packages }... ... Disconnect and reconnect/127.0.0.1:63893 lino-learn-netty client start done. Link report starts Link report information: This client is linked to the server. channelId:c9ad1077 Link reporting IP: 127.0.0.1 Link Report Port: 63926 Link report completed lino-learn-netty client start done. 2023-02-28T16:26:23.135 Message received: Notify the client that the link is established successfully Tue Feb 28 16:26:23 CST 2023 127.0.0.1 2023-02-28T16:26:25.137 Message received: Read waiting: Client are you there [ctx.close()]{<!-- -->I end with a newline character for processing half-package sticky packages }... ... Disconnect and reconnect/127.0.0.1:63926 lino-learn-netty client start done. Link report starts Link report information: This client is linked to the server. channelId: f56eed9f Link reporting IP: 127.0.0.1 Link Report Port: 63959 Link report completed lino-learn-netty client start done. 2023-02-28T16:26:25.163 Message received: Notify the client that the link is established successfully Tue Feb 28 16:26:25 CST 2023 127.0.0.1