This is the 10th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Introduction to the

We are in the process of using the client and server connection, may be because of all sorts of problems lead to the client and the server connection is interrupted, encounter this kind of situation, usually we need to use the monitor to monitor the client and the server connection, if the first time found that connection is broken, will need to manually to reconnection. More trouble, today to introduce a netty automatic reconnect way.

Use Netty to establish a connection

To set up a connection with Netty, you need to start the server first. Normally, the server starts with ServerBootstrap, as shown below:

// Bind the PORT and start ChannelFuture. F = b.ind (PORT).sync();Copy the code

For the client, Bootstrap can be used as follows:

ChannelFuture = b.connector (HOST, PORT).sync();Copy the code

Principle of automatic reconnection

So when the connection between the client and the server is broken, how to automatically reconnect?

For the client, automatic reconnection only requires another call to Bootstrap’s connect method. The key question now is how to find the time to call Connect again.

We know that both the server and the client need to register a special handler to handle messages.

To read news, generally need to inherit ChannelInboundHandlerAdapter, defines a lot in this handler and channel on life cycle method, we can start from these life cycle method.

In general, the state of the connection between the client and server is:

CHANNEL REGISTERED– “CHANNEL ACTIVE –” READ — “READ COMPLETE –” CHANNEL INACTIVE — “CHANNEL UNREGISTERED

If the connection between the client and the server is closed, two events will be triggered: CHANNEL INACTIVE and CHANNEL UNREGISTERED. In this case, we can rewrite the following two methods on the client and add the reconnection logic in the methods.

@override public void channelInactive(final ChannelHandlerContext CTX) {println(" Connection is broken :" + ctx.channel().remoteAddress()); } @Override public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception { println("sleep:" + ReconnectClient.RECONNECT_DELAY + 's'); Ctx.channel ().eventloop ().schedule(() -> {println(" reconnect: "+ reconnectClient.host + ':' + reconnectClient.port); ReconnectClient.connect(); }, ReconnectClient.RECONNECT_DELAY, TimeUnit.SECONDS); }Copy the code

In the channelInactive method, we just print some logs. The main logic is in the channelUnregistered method, where we first get the current channel through CTX, then get the eventLoop in the channel, then call its schedule method, and then re-call the connect() method after a given time.

Connect () returns a ChannelFuture, so you can add a listener to the ChannelFuture to listen for the status of the connect.

The connect method defined here is as follows:

static void connect() { bs.connect().addListener(future -> { if (future.cause() ! = null) { handler.startTime = -1; Handler.println (" Failed to establish connection: "+ future.cause()); }}); }Copy the code

Analog automatic reconnection

In the last section, we learned how to auto-reconnect. This section will simulate auto-reconnect.

I’m going to introduce a class called IdleStateHandler, which, as you can see from its name, triggers this Idle state when a Channel doesn’t do any read or write operations.

The Idle class is called IdleStateEvent. Idle has six states: FIRST_READER_IDLE_STATE_EVENT, READER_IDLE_STATE_EVENT, FIRST_WRITER_IDLE_STATE_EVENT, WRITER_IDLE_STATE_EVENT, FIRST_ALL_IDLE_STATE_EVENT, and ALL_IDLE_STATE_EVENT.

Indicates the read state IDLE, write state IDLE, and read and write state IDLE.

This allows us to add IdleStateHandler when the client is started. If the client has not read any messages from the server for a while, we call ctx.close() to close the channel and start the reconnect operation on the client.

bs.group(group) .channel(NioSocketChannel.class) .remoteAddress(HOST, PORT) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new IdleStateHandler(READ_TIMEOUT, 0, 0), handler); }});Copy the code

IdleStateEvent is a user-triggered event. To capture this event, override userEventTriggered:

public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { if (! (evt instanceof IdleStateEvent)) { return; } IdleStateEvent e = (IdleStateEvent) evt; If (e.state() == idlestate.reader_idle) {println(" in Idle state, close connection "); ctx.close(); }}Copy the code

In the example above, we capture the IdleStateEvent and decide that if the state of IdleState is IDleState.reader_IDLE, then we close the channel.

conclusion

In this article, we introduce the principle of reconnection and user-triggered events. I hope you enjoy it.

An example for this article is learn-Netty4

This article is available at www.flydean.com/09-netty-re…

The most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the small skills waiting for you to find!

Welcome to follow my public number: “procedures those things”, understand technology, more understand you!