1 AbstractChannel

1.1 AbstractChannel structure

A channel is a core concept of Netty. It represents a network connection and communicates with the peer end. Data can be written to or read from the peer end.

AbstractChannel, an abstract Netty channel class, has the following constructor:

private final DefaultChannelPipeline pipeline;
private final Channel parent;

protected AbstractChannel(Channel parent) {
    this.parent = parent; / / parent channel
    id = newId();
    // Create an underlying NIO channel to perform the actual I/O operations
    unsafe = newUnsafe();
    // Create a new channel pipeline
    pipeline = newChannelPipeline();
}
Copy the code
  • The newUnsafe method, which is implemented in a concrete subclass, is abstract

  • AbstractChannel has a pipeline property inside that represents the pipeline of the processor. When Netty initializes a channel, it initializes the Pipeline property as an instance of DefaultChannelPipeline. Indicates that each channel has a ChannelPipeline processor.

AbstractChannel has an internal parent channel property that holds the channel’s parent.

  • For connection listening channels (such as NioServerSocketChannel), the parent property is null;
   public NioServerSocketChannel(ServerSocketChannel channel) {
       // Parent wears a null
     super(null, channel, SelectionKey.OP_ACCEPT);
     config = new NioServerSocketChannelConfig(this, javaChannel().socket());
 }
Copy the code
  • For transport channels (such as NioSocketChannel), the value of the parent property is the listening channel that received the connection.

Almost all Netty channel implementation classes inherit AbstractChannel classes and have the parent and Pipeline property members above.

1.2 AbstractChannel main methods

// This method connects to a remote server.
// Method takes the address of the remote server and returns immediately after it is called
// Its return value is ChannelFuture, the asynchronous task that performs the connection operation.
// This method is used in the client transport channel.
ChannelFuture connect(SocketAddress address)

// Start listening for new client connections by binding the listener address.
// This method is called when a new connection to the server listens and receives channels.
ChannelFuture bind(SocketAddress address)

// This method closes the channel connection and returns the ChannelFuture asynchronous task with the connection closed.
// If you need to perform other operations after the connection is officially closed, you need to set callback methods for asynchronous tasks;
// Or call the sync() method of the ChannelFuture asynchronous task to block the current thread until the ChannelFuture asynchronous task completes.
ChannelFuture close(a);

// This method reads channel data and starts inbound processing.
// Specifically, to read data from the internal Java NIO Channel,
// Then start the internal Pipeline Pipeline, start the data read inbound processing.
// The return channel of this method is itself used for chained calls.
Channel read(a)

// The function of this method is to start the outbound flow treatment,
// Write the final processed data to the underlying channel (such as the Java NIO channel).
// The return value of this method is an asynchronous processing task for outbound processing.ChannelFuture Write (Object O)// This method immediately writes out the data in the buffer to the peer end.
// When calling the previous write() outbound processing, the data cannot be written directly to the peer,
For the most part, write is just writing to the operating system buffer,
// The operating system determines when to write data to the peer based on the condition of the buffer.
// Executing flush() immediately writes the buffer's data to the peer end.
Channel flush(a)
Copy the code

2 EmbeddedChannel: EmbeddedChannel

. The general process of unit test is as follows: first add Handler service processor to Pipeline Pipeline of channel, then start Netty server and client program successively, send messages to each other, and test the effect of service processor.

There is a problem with these complex processes: if each business processor is developed with repeated startup of the server and client, the whole process is cumbersome and time consuming. How do you solve this unproductive, inefficient duplication of effort? Netty provides a dedicated channel, an EmbeddedChannel.

EmbeddedChannel simply simulates inbound and outbound operations, with no actual transmissions under the hood and no need to start Netty servers and clients. The event mechanism and processing of an EmbeddedChannel is exactly the same as that of a real transport channel, except that it does not transmit. Therefore, using EmbeddedChannel, developers can easily and quickly unit test ChannelHandler business processors in unit test cases.

To simulate the sending and receiving of data, EmbeddedChannel provides a specialized set of methods,

// Write inbound data to the channel to simulate a real data receiving scenario
// This data is processed by an inbound processor on the pipeline
public boolean writeInbound(Object... msgs)

// read the inbound data from the EmbeddedChannel and return through the pipeline end
// An inbound processor processes inbound data after completion
// Return null if there is no data
public <T> T readInbound(a)

// Write outbound data to the channel to simulate a real channel sending data scenario
// will be processed by the outbound processor on the pipeline
public boolean writeOutbound(Object... msgs)

// read the station data from the EmbeddedChannel and return through the pipeline end
// An outbound processor processes outbound data after completion
// Return null if there is no data
public <T> T readOutbound(a) 

// End the EmbeddedChannel, calling the close method of the channel
public boolean finish(a)
Copy the code

The EmbeddedChannel class has both generic interfaces and methods for channels and adds some helper methods for unit testing, which can be very useful in development