This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

Introduction to the

Channel is the bridge connecting ByteBuf and Event. The Channel in Netty provides a unified API. Through this unified API, Netty can easily connect with various transmission types, such as OIO and NIO. Today’s article will introduce the use of channels and some concepts related to channels.

The Channel,

What is a Channel? A Channel is a bridge between network input and I/O processing. You can use a Channel to determine whether the current state is open or connected. You can also determine which IO operations are supported by the current Channel. You can also use ChannelPipeline to process messages in the Channel.

Let’s look at the definition of a Channel:

public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {
Copy the code

As you can see, Channel is an interface that inherits from AttributeMap, ChannelOutboundInvoker, and Comparable. Comparable means that this class can be used for comparison. AttributeMap is used to store the attributes of a Channel. The ChannelOutboundInvoker is responsible for connecting and writing to an external SocketAddress.

Take a look at the methods defined in the channel:

As you can see, there are a variety of methods defined in a channel. What are the characteristics of these methods? Next, I will explain each of them.

Asynchronous IO and ChannelFuture

All I/O in Netty are asynchronous I/OS, which means all I/O are returned immediately. When I/O is returned, I/O may not be finished yet, so I/O needs to return a ChannelFuture. When I/O has a result, I/O will notify the ChannelFuture, so that it can fetch the result.

ChannelFuture is Java. The util. Concurrent. The Future of the subclass, it besides can get a thread of execution result, also extends to its, joined the current task state judgment, waiting for the task execution, and add the function of the listener.

The rest of the functionality is well understood, but the breakthrough is the ability to add a listener to the ChannelFuture. Here’s a way to add a listener:

Future<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);
Copy the code

The Listener will be notified when the Future finishes executing. No need to call get and wait for the Future to finish. This is actually the implementation of the concept of asynchronous IO, you don’t have to call it, you just let me know when you’re done. Very nice!

The status of the ChannelFuture is uncompleted or Completed, which indicates the execution status of the task.

When an IO has just started, return a ChannelFuture object whose initial state is Uncompleted. Note that the IO in this state is not working yet. When the I/O is completed, the ChannelFuture status changes to Completed whether it is succeeded, failed, or cancelled.

The following figure shows the mapping between ChannelFuture status and I/O status:

                                    +---------------------------+
                                    | Completed successfully    |
                                    +---------------------------+
                               +---->      isDone() = true      |
Copy the code

+ — — — — — + | | isSuccess = true () | | Uncompleted | | + = + + — — — — — + | | Completed with failure | | isDone () = false | | + — — — — — + | isSuccess = false () | — – + — – > isDone () = true | | isCancelled () = false | | | cause () = non – null | | Cause () = null | | + = + + — — — — — + | | Completed by cancellation | | + — — — — – + + – – > isDone () = true | | isCancelled () = true | + — — — — – +

To monitor IO status, add a ChannelFutureListener for ChannelFuture using the addListener method mentioned above.

There is also an await() method to wait for the IO to complete, but this method will wait for the IO to complete and is a synchronous method, so it is not recommended.

In contrast, addListener(GenericFutureListener) is a non-blocking asynchronous method that adds a ChannelFutureListener to ChannelFuture, When I/O is over, it will automatically notify ChannelFutureListener, which is very useful.

To avoid IO blocking, do not call await() in the IO method of the ChannelHandler. This may result in performance degradation of the ChannelHandler due to IO blocking.

Here are two examples of an incorrect operation and a correct operation:

@override public void channelRead(ChannelHandlerContext CTX, Object msg) { ChannelFuture future = ctx.channel().close(); future.awaitUninterruptibly(); @override public void channelRead(ChannelHandlerContext CTX, Object msg) { ChannelFuture future = ctx.channel().close(); Future.addlistener (new ChannelFutureListener() {public void operationComplete(ChannelFuture Future) {// call the other logic}}); }Copy the code

You can see the difference between the two.

Note also that these await methods in ChannelFuture are such as: Await (long), await(long, TimeUnit), awaitUninterruptibly(long), or awaitUninterruptibly(long, TimeUnit) can carry an expiration time, I/O: I/o: I/o: I/o: I/o: I/o: I/o: I/o: I/o: I/o: I/o: I/o

Bootstrap b = ... ; ChannelFuture f = b.connect(...) ; f.awaitUninterruptibly(10, TimeUnit.SECONDS); If (f.isCancelled()) {if (f.I sCancelled()) {if (f.I sCancelled())} else if (f.I sCancelled()) { F.cause ().printStackTrace(); f.cause().printStackTrace(); } else {// Connection successfully established}Copy the code

The above code can be changed to the following example:

Bootstrap b = ... ; // Configure b.option(channeloption.connect_timeout_millis, 10000); ChannelFuture f = b.connect(...) ; f.awaitUninterruptibly(); Assert fisdone (); // Wait until the underlying I/O is executed. If (f.isCancelled()) {if (f.I sCancelled())} else if (! f.isSuccess()) { f.cause().printStackTrace(); } else {// Connection successfully established}Copy the code

The hierarchy of channels

Channels in Netty are hierarchical, which can be accessed through the parent property. The object parent gets depends on how the Channel was created. For example, if it is a SocketChannel accepted by ServerSocketChannel, then its parent is ServerSocketChannel.

Release resources

Like all IO, a Channel needs to be released when it is used up, either by calling close() or close(ChannelPromise).

The event processing

A channel is responsible for establishing a connection, which can be used to handle the event ChannelEvent. In fact, channelEvents are handled by each of the defined channelHandlers. ChannelPipeline is a bridge connecting channel and channelHandler.

We will explain the relationship between ChannelEvent, Channelhandler and ChannelPipeline in detail in the next chapter, please stay tuned.

conclusion

A Channel is a key Channel in Netty. Events and handlers run on the basis of a Channel. So a Channel is the foundation of netty.

This article is available at www.flydean.com/04-netty-ch…

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!