This is the 16th day of my participation in the August Text Challenge.More challenges in August

1. Introduction to Netty core Components

Netty consists of the following core components:

Channel 2, callback 3, Future 4, event and ChannelHandler

These building blocks represent different types of constructs: resources, logic, and advice. Your application will use them to access the network and the data flowing through it.

Second, the Channel

A Channel is a basic construct of JavaNIO.

It represents an open connection to an entity, such as a hardware device, a file, a network socket, or a program component that can perform one or more different I/O operations, such as read and write operations.

Currently, a Channel can be thought of as a carrier for incoming (inbound) or outgoing (outbound) data. Therefore, it can be turned on or off, connected or disconnected.

Third, the callback

A callback is really just a method, a reference to a method that has been provided to another method. This allows the latter to call the former when appropriate. Callbacks are used in a wide range of programming scenarios and are one of the most common ways to notify interested parties when an operation has been completed.

Netty internally uses callbacks to handle events; When a callback is triggered, the associated event can be handled by an implementation of interface-ChannelHandler. The following code listing shows an example: When a new connection has been established, the ChannelHandler’s channelActive() callback will be called and a message will be printed.

/** * Create by Lovebugs on 2021/8/15 * ChannelHandler triggered by callback */
public class ConnectHandler extends ChannelInboundHandlerAdapter {
    /** * channelActive(ChannelHandlerContext) is called when a new connection has been created@param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("Client " + ctx.channel().remoteAddress() + " connected"); }}Copy the code

Third, the Future

The Future provides another way to notify the application when an operation is complete. This object can be thought of as a placeholder for the result of an asynchronous operation; It will be completed at some point in the future and provide access to its results.

The Interface Java JDK preset. Util. Concurrent. The Future, but its implementation, provided only allows manually check to see if the corresponding operation has been completed, or has been blocked until it is completed. This can be tedious, so Netty provides its own implementation, ChannelFuture, for use when performing asynchronous operations. ChannelFuture provides several additional methods that enable us to register one or more instances of ChannelFutureListener. The listener’s callback method, operationComplete(), will be called when the corresponding operation completes. The listener can then determine whether the operation completed successfully or if it went wrong. If it is the latter, we can retrieve the resulting Throwable. In short, the notification mechanism provided by ChannelFutureListener eliminates the need to manually check that the corresponding operation has completed. Each Netty outbound I/O operation returns a ChannelFuture; In other words, they don’t block. So Netty completion is asynchronous and event-driven.

The following code listing shows how to use ChannelFutureListener. First, connect to the remote node, where the connect method returns directly and does not block. Then, register a new ChannelFutureListener on the ChannelFuture returned by the call to the connect() method. When the listener is notified that the connection has been established, the corresponding status is checked. If the operation succeeds, the data is written to the Channel; Otherwise, the corresponding Throwable is retrieved from ChannelFuture.

Channel channel = new NioSocketChannel();
// Connect to a remote node asynchronously (Does not block)
ChannelFuture future = channel.connect(new InetSocketAddress("192.168.0.1".25));
// Register a ChannelFutureListener to be notified when the operation is complete
future.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture future) throws Exception {
        // Check the status of the operation
        if (future.isSuccess()) {
            // Create a ByteBuf to hold data
            ByteBuf buffer = Unpooled.copiedBuffer("Hello", Charset.defaultCharset());
            // Send data asynchronously to the remote node and return a ChannelFuture
            ChannelFuture wf = future.channel().writeAndFlush(buffer);
            / /...
        } else {
            // An error occursThrowable cause = future.cause(); cause.printStackTrace(); }}});Copy the code

It’s important to note that error handling is up to you, your goals, and of course any current restrictions on specific types of errors. If you think of ChannelFutureListener as a more refined version of the callback, you’re right. In fact, callback and Future are complementary mechanisms; Together, they form one of the key building blocks of Netty itself.

Events and ChannelHandler

Netty uses different events to notify us of state changes or the status of operations. This allows us to trigger appropriate actions based on events that have already occurred. These actions might be:

  • Log;
  • Data conversion;
  • Flow control;
  • Application logic.

Netty is a network programming framework, so events are classified by their relevance to inbound or outbound data flows. Events that may be triggered by inbound data or related state changes include:

  • The connection has been activated or deactivated.
  • Data reading;
  • User events;
  • Error events

Each event can be distributed to a user-implemented method in the ChannelHandler class. This is a good example of translating the event-driven paradigm directly into an application building block. The following figure shows how an event is handled by one of these ChannelHandler chains.

Netty provides a number of predefined ChannelHandler implementations ready out of the box, including ChannelHandler for various protocols such as HTTP and SSL/TLS. Internally, The ChannelHandler itself uses events and futures, making them consumers of the same abstractions your application will use.