Netty
Bootstrap
A Bootstrap
that makes it easy to bootstrap a Channel
to use for clients.
The bind()
methods are useful in combination with connectionless transports such as datagram (UDP).
For regular TCP connections, please use the provided connect()
methods.
decoder,它的用处是将读取的byte数据转化为用户自己定义的数据类型
encoder,用于将用户定义的类型转化为byte类型,这样才能通过channel发送出去。。。
ByteToMessageDecoder
ChannelInboundHandlerAdapter
adapter的作用就是比较粗糙的实现方法,用户可以继承它然后重写自己感兴趣的方法,
pipeline上面调用write方法的时候,netty会从pipeline的后面向前寻找合适的outboundhandler用于处理要写的数据,而且是先将数据存放到handler的buffer里面,真正的写数据则是调用flush方法实现的。。。
ChannelInboundHandler
ChannelHandler
which adds callbacks for state changes. This allows the user to hook in to state changes easily.
ChannelOutboundHandler
ChannelHandler
which will get notified for IO-outbound-operations.
EventLoopGroup
Special EventExecutorGroup
which allows registering Channel
s that get processed for later selection during the event loop.
NioEventLoopGroup
Create a new instance using the specified number of threads, ThreadFactory
and the SelectorProvider
which is returned by SelectorProvider.provider()
.
newFixedThreadPool
-
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
-
At any point, at most
nThreads
threads will be active processing tasks. -
If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.
-
If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.
-
The threads in the pool will exist until it is explicitly
shutdown
.
server.childHandler
Set the ChannelHandler
which is used to serve the request for the Channel
's.
ChannelPipeline
A list of ChannelHandler
s which handles or intercepts inbound events and outbound operations of a Channel
. ChannelPipeline
implements an advanced form of the Intercepting Filter pattern to give a user full control over how an event is handled and how the ChannelHandler
s in a pipeline interact with each other.
Creation of a pipeline
Each channel has its own pipeline and it is created automatically when a new channel is created.
How an event flows in a pipeline
The following diagram describes how I/O events are processed by ChannelHandler
s in a ChannelPipeline
typically. An I/O event is handled by either a ChannelInboundHandler
or a ChannelOutboundHandler
and be forwarded to its closest handler by calling the event propagation methods defined in ChannelHandlerContext
, such as ChannelHandlerContext.fireChannelRead(Object)
and ChannelHandlerContext.write(Object)
.
I/O Request viaChannel
orChannelHandlerContext
| +---------------------------------------------------+---------------+ | ChannelPipeline | | | \|/ | | +---------------------+ +-----------+----------+ | | | Inbound Handler N | | Outbound Handler 1 | | | +----------+----------+ +-----------+----------+ | | /|\ | | | | \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler N-1 | | Outbound Handler 2 | | | +----------+----------+ +-----------+----------+ | | /|\ . | | . . | | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()| | [ method call] [method call] | | . . | | . \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 2 | | Outbound Handler M-1 | | | +----------+----------+ +-----------+----------+ | | /|\ | | | | \|/ | | +----------+----------+ +-----------+----------+ | | | Inbound Handler 1 | | Outbound Handler M | | | +----------+----------+ +-----------+----------+ | | /|\ | | +---------------+-----------------------------------+---------------+ | \|/ +---------------+-----------------------------------+---------------+ | | | | | [ Socket.read() ] [ Socket.write() ] | | | | Netty Internal I/O Threads (Transport Implementation) | +-------------------------------------------------------------------+
An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the diagram. The inbound data is often read from a remote peer via the actual input operation such as SocketChannel.read(ByteBuffer)
. If an inbound event goes beyond the top inbound handler, it is discarded silently, or logged if it needs your attention.
An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests. If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the Channel
. The I/O thread often performs the actual output operation such as SocketChannel.write(ByteBuffer)
.
InboundEvent
ChannelFuture
The result of an asynchronous Channel
I/O operation.
All I/O operations in Netty are asynchronous. It means any I/O calls will return immediately with no guarantee that the requested I/O operation has been completed at the end of the call. Instead, you will be returned with a ChannelFuture
instance which gives you the information about the result or status of the I/O operation.
A ChannelFuture
is either uncompleted or completed. When an I/O operation begins, a new future object is created. The new future is uncompleted initially - it is neither succeeded, failed, nor cancelled because the I/O operation is not finished yet. If the I/O operation is finished either successfully, with failure, or by cancellation, the future is marked as completed with more specific information, such as the cause of the failure. Please note that even failure and cancellation belong to the completed state.
+---------------------------+ | Completed successfully | +---------------------------+ +----> isDone() = true | +--------------------------+ | | 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 | +---------------------------+
Various methods are provided to let you check if the I/O operation has been completed, wait for the completion, and retrieve the result of the I/O operation. It also allows you to add ChannelFutureListener
s so you can get notified when the I/O operation is completed.
Prefer addListener(GenericFutureListener)
to await()
It is recommended to prefer addListener(GenericFutureListener)
to await()
wherever possible to get notified when an I/O operation is done and to do any follow-up tasks.
addListener(GenericFutureListener)
is non-blocking. It simply adds the specified ChannelFutureListener
to the ChannelFuture
, and I/O thread will notify the listeners when the I/O operation associated with the future is done. ChannelFutureListener
yields the best performance and resource utilization because it does not block at all, but it could be tricky to implement a sequential logic if you are not used to event-driven programming.
By contrast, await()
is a blocking operation. Once called, the caller thread blocks until the operation is done. It is easier to implement a sequential logic with await()
, but the caller thread blocks unnecessarily until the I/O operation is done and there's relatively expensive cost of inter-thread notification. Moreover, there's a chance of dead lock in a particular circumstance, which is described below.
Do not call await()
inside ChannelHandler
The event handler methods in ChannelHandler
is usually called by an I/O thread. If await()
is called by an event handler method, which is called by the I/O thread, the I/O operation it is waiting for might never be complete because await()
can block the I/O operation it is waiting for, which is a dead lock.