This document is compiled from Han Shunping Netty tutorial of shangsilicon valley
https://www.bilibili.com/video/BV1DJ411m7NR
1,Bootstrap,ServerBootstrap
Bootstrap means boot. A Netty application usually starts with a bootstrap. Its main function is to configure the whole Netty program and connect various components in series. Bootstrap class in Netty is the boot class of client program, and ServerBootstrap is the boot class of server
Common methods:
Method name | Method introduction |
---|---|
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) | This method is used on the server side to set two eventloops |
public B group(EventLoopGroup group) | This method is used for the client to set an EventLoop |
public B channel(Class<? extends C> channelClass) | This method is used to set up a server-side channel implementation |
public <T> B option(ChannelOption<T> option, T value) | Used to add a channel to the server configuration |
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) | Used to add configuration to the received channel |
public ServerBootstrap childHandler(ChannelHandler childHandler) | This method is used to set the business processing class (custom handler) |
public ChannelFuture bind(int inetPort) | This method is used on the server side to set the occupied port number |
public ChannelFuture connect(String inetHost, int inetPort) | This method is used for the client to connect to the server |
2,Future,ChannelFuture
All IO operations in Netty are asynchronous, and it is impossible to know immediately whether the message is processed correctly. However, you can wait for it to complete or register a listener directly. The specific implementation is that they can register a listener through Future and ChannelFuture. When the operation succeeds or fails, the listener will automatically trigger the registered listening event
Common methods
Method name | Method introduction |
---|---|
Channel channel() | Returns the channel for which the IO operation is currently in progress |
ChannelFuture sync() | Waiting for the asynchronous operation to complete is equivalent to blocking the current. |
3,Channel
- The component of Netty network communication, which can be used to perform network I/O operations.
- Through Channel, you can obtain the status of the Channel currently connected to the network
- The configuration parameters of the network connection (such as the size of the receive buffer) can be obtained through the Channel
- Channel provides asynchronous network I/O operations (such as establishing connection, reading and writing, binding port). Asynchronous call means that any I/O call will be returned immediately, and it does not guarantee that the requested I/O operation has been completed at the end of the call
- The call immediately returns an instance of ChannelFuture. By registering the listener on ChannelFuture, you can call back to notify the caller when the I/O operation succeeds, fails or cancels
- Support associated I/O operations and corresponding handlers
- Connections with different protocols and blocking types have different Channel types corresponding to them
Common Channel types
name | introduce |
---|---|
NioSocketChannel | Asynchronous client TCP Socket connection. |
NioServerSocketChannel | Asynchronous server-side TCP Socket connection |
NioDatagramChannel | Asynchronous UDP connection. |
NioSctpChannel | Asynchronous client Sctp connection. |
NioSctpServerChannel | Asynchronous Sctp server-side connection. These channels cover UDP and TCP network IO and file IO. |
4,Selector
- Netty implements I/O multiplexing based on Selector object. One thread of Selector can listen to Channel events of multiple connections.
- After registering a Channel with a Selector, the internal mechanism of the Selector can automatically and continuously query (Select) whether these registered channels have ready I/O events (such as readable, writable, network connection completion, etc.), so that the program can simply use one thread to efficiently manage multiple channels
- At the same time, the selectedKey set in the Selector is replaced by a set set implemented by itself in Netty, which is more efficient.
5. ChannelHandler and its implementation class
- ChannelHandler is an interface that handles I/O events or intercepts I/O operations and forwards them to the next handler in its channelpipeline.
- ChannelHandler itself does not provide many methods, because this interface has many methods that need to be implemented. During use, it can inherit its subclasses
- We often need to customize a Handler class to inherit the ChannelInboundHandlerAdapter, and then implement the business logic by rewriting the corresponding methods. Next, let's see which methods we generally need to override
public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler { //Channel registration event @Skip @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelRegistered(); } //Channel deregistration event @Skip @Override public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelUnregistered(); } //Channel ready event @Skip @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelActive(); } /** * Calls {@link ChannelHandlerContext#fireChannelInactive()} to forward * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. * * Sub-classes may override this method to change behavior. */ @Skip @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelInactive(); } //Channel read data event @Skip @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { ctx.fireChannelRead(msg); } //Event triggered after reading channel data @Skip @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelReadComplete(); } /** * Calls {@link ChannelHandlerContext#fireUserEventTriggered(Object)} to forward * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. * * Sub-classes may override this method to change behavior. */ @Skip @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { ctx.fireUserEventTriggered(evt); } /** * Calls {@link ChannelHandlerContext#fireChannelWritabilityChanged()} to forward * to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}. * * Sub-classes may override this method to change behavior. */ @Skip @Override public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { ctx.fireChannelWritabilityChanged(); } //An abnormal event occurred in the channel @Skip @Override @SuppressWarnings("deprecation") public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.fireExceptionCaught(cause); } }
- ChannelInboundHandler is used to handle inbound I/O events.
- ChannelOutboundHandler is used to handle outbound I/O operations.
Adapter
- The ChannelInboundHandlerAdapter is used to handle inbound I/O events.
- The ChannelOutboundHandlerAdapter is used to handle outbound I/O operations.
- ChannelDuplexHandler is used to handle inbound and outbound events.
6. Pipeline and ChannelPipeline
- ChannelPipeline is a collection of handlers, which is responsible for handling and intercepting inbound or outbound events and operations. It is equivalent to a chain running through Netty. (it can also be understood in this way: ChannelPipeline is a List that saves ChannelHandler and is used to handle or intercept inbound events and outbound operations of Channel)
- ChannelPipeline implements an advanced form of interception filter mode, which enables users to fully control the processing of events and how the channelhandlers in the Channel interact with each other
- In Netty, each Channel has and only one ChannelPipeline corresponds to it
- A Channel contains a ChannelPipeline, which maintains a two-way linked list composed of ChannelHandlerContext, and each ChannelHandlerContext is associated with a ChannelHandler
- Inbound events and outbound events are in a two-way linked list. Inbound events will be passed from the head of the linked list to the last inbound handler, and outbound events will be passed from the tail of the linked list to the first outbound handler. The two types of handlers do not interfere with each other
Common methods:
Method name | introduce |
---|---|
ChannelPipeline addFirst(ChannelHandler... handlers) | Add a business handler to the first position in the chain |
ChannelPipeline addLast(ChannelHandler... handlers) | Add a business handler to the last position in the chain |
7,ChannelHandlerContext
- Save all context information related to the Channel and associate a ChannelHandler object at the same time
- That is, the ChannelHandlerContext contains a specific event handler. At the same time, the ChannelHandlerContext is also bound with the corresponding pipeline and Channel information to facilitate the call of ChannelHandler
Common methods:
Method name | introduce |
---|---|
ChannelFuture close() | Close channel |
ChannelOutboundInvoker flush() | Refresh |
ChannelFuture writeAndFlush(Object msg) | Write data to the next ChannelHandler of the current ChannelHandler in the ChannelPipeline and start processing (outbound) |
8,ChannelOption
After creating a Channel instance, Netty generally needs to set the ChannelOption parameter.
The ChannelOption parameters are as follows:
- ChannelOption. SO_ The TCP / log backup function is used to initialize the IP connection size of the server. The server processes client connection requests in sequence, so only one client connection can be processed at a time. When multiple clients come, the server puts the client connection requests that cannot be processed in the queue for processing. The backlog parameter specifies the size of the queue.
- ChannelOption.SO_KEEPALIVE: keep the connection active all the time
9. EventLoopGroup and its implementation class NioEventLoopGroup
-
EventLoopGroup is an abstraction of a group of eventloops. In order to make better use of multi-core CPU resources, Netty generally has multiple eventloops working at the same time, and each EventLoop maintains a Selector instance.
-
EventLoopGroup provides the next interface. You can get one of the eventloops from the group according to certain rules to process tasks. In Netty server-side programming, we generally need to provide two eventloopgroups, such as BossEventLoopGroup and WorkerEventLoopGroup.
-
Usually, a service port, that is, a ServerSocketChannel, corresponds to a Selector and an EventLoop thread. BossEventLoop is responsible for receiving the connection from the client and handing the SocketChannel to the WorkerEventLoopGroup for IO processing, as shown in the following figure:
-
BossEventLoopGroup is usually a single threaded EventLoop. EventLoop maintains a Selector instance registered with ServerSocketChannel. BossEventLoop constantly polls the Selector to separate connection events
-
Usually OP_ACCEPT event, and then give the received SocketChannel to the WorkerEventLoopGroup
-
WorkerEventLoopGroup will select one of the eventloops by next to register the SocketChannel with its maintained Selector and handle its subsequent IO events
Common methods:
Method name | introduce |
---|---|
public NioEventLoopGroup() | Construction method |
public Future<?> shutdownGracefully() | Disconnect and close the thread |
10,Unpooled
Netty provides a tool class specially used to operate buffers (that is, netty's data container)
common method
Method name | introduce |
---|---|
public static ByteBuf copiedBuffer(CharSequence string, Charset charset) | Returns a ByteBuffer object through the given data and character encoding (similar to the ByteBuffer in NIO, but different) |
Code example
//Create a ByteBuf //1. Create an object that contains an array and is a byte[10] //2. In the buffer of netty, it is unnecessary to use flip to reverse the data before reading it // The bottom layer maintains readerIndex and writeIndex //The range written to the buffer is [writeIndex, capacity) //The readable range in the buffer is [readerIndex, writeindex]. Using buf.readByte() will move the readerIndex pointer backward, and using buf.getByte(i) to get through the index will not move the pointer ByteBuf byteBuf = Unpooled.buffer(10); for (int i = 0; i < 10; i++) { byteBuf.writeByte(i); } //Gets the size of the buf int capacity = byteBuf.capacity(); //output for (int i = 0; i < byteBuf.capacity(); i++) { System.out.println(byteBuf.getByte(i)); System.out.println(byteBuf.readByte()); } byte[] content = byteBuf.array(); //Convert content to string String c = new String(content, StandardCharsets.UTF_8); //Array offset int offset = byteBuf.arrayOffset(); //Get read offset int readerIndex = byteBuf.readerIndex(); //Get write offset int writerIndex = byteBuf.writerIndex(); //Get capacity int capacity = byteBuf.capacity(); //Gets the number of bytes that can be read int readableBytes = byteBuf.readableBytes(); //Get bytes of a location by index byte aByte = byteBuf.getByte(0); //Gets the character sequence of a range in Buf CharSequence charSequence = byteBuf.getCharSequence(0, 4, StandardCharsets.UTF_8);
11. Netty group chat system
Example requirements:
- Write a Netty group chat system to realize simple data communication between server and client (non blocking)
- Realize multi crowd chat
- Server side: it can monitor users online and offline, and realize message forwarding function
- Client: through the channel, it can send messages to all other users without blocking, and accept messages sent by other users (forwarded by the server)
- Objective: to further understand the programming mechanism of Netty non blocking network
Server side code:
/*************Startup class**************/ public class GroupChatServer { private int port; //Listening port public GroupChatServer(int port){ this.port = port; } //Write the run method to process the request of the client public void run() throws InterruptedException { //Create two thread groups NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast("decoder", new StringDecoder()); //Add decoder to pipeline pipeline.addLast("encoder", new StringEncoder()); //Add encoder pipeline.addLast(new GroupChatServerHandler()); } }); System.out.println("netty Server startup"); ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); //Listen for closing events channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { GroupChatServer groupChatServer = new GroupChatServer(7000); groupChatServer.run(); } } /***********************Handler**********************/ public class GroupChatServerHandler extends SimpleChannelInboundHandler<String> { //Define a channel group to manage all channels //GlobalEventExecutor.INSTANCE is a global event executor and a single instance private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //This method indicates that the connection is established. Once the connection is established, it will be executed first @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); //This method will traverse all channels in the channelGroup and send messages instead of traversing ourselves channelGroup.writeAndFlush("[client]" + channel.remoteAddress() + sdf.format(new Date()) + "join the chat\n"); //Add the current Channel to the ChannelGroup channelGroup.add(channel); } //Indicates that the channel is active and prompts xxx to go online @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + " " + sdf.format(new Date()) + "It's online~"); } //Indicates that the channel is inactive, prompting xxx to go offline @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + " " + sdf.format(new Date()) + "Offline~"); } //Indicates that the channel is disconnected and pushes xx customer's departure information to the current online customer @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); channelGroup.writeAndFlush("[client]" + channel.remoteAddress() +" "+ sdf.format(new Date()) + "I am leaving\n"); System.out.println("current channelGroup size:" + channelGroup.size()); } //Read the data and forward the message @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { //Get current channel Channel channel = ctx.channel(); //At this time, traverse the channelGroup and send back different messages according to different situations channelGroup.forEach(item -> { if (item != channel) { item.writeAndFlush("[customer]" + channel.remoteAddress() + "Message sent:" + msg + "\n"); } else { //Send your message to yourself item.writeAndFlush("[own]Message sent:" + msg + "\n"); } }); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { ctx.close(); } }
Client code:
/*********************Startup class******************/ public class GroupChatClient { //attribute private final String host; private final int port; public GroupChatClient(String host, int port) { this.port = port; this.host = host; } public void run() throws InterruptedException { NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(eventExecutors) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //Join Handler pipeline.addLast("decoder", new StringDecoder()); pipeline.addLast("encoder", new StringEncoder()); pipeline.addLast(new GroupChatClientHandler()); } }); ChannelFuture channelFuture = bootstrap.connect(host, port).sync(); //Get channel Channel channel = channelFuture.channel(); System.out.println("--------" + channel.localAddress() + "---------"); //The client needs to enter information to create a scanner Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()){ String msg = scanner.nextLine(); //Send to the server through channel channel.writeAndFlush(msg + "\r\n"); } } finally { eventExecutors.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { new GroupChatClient("127.0.0.1", 7000).run(); } } /*****************Handler*****************/ public class GroupChatClientHandler extends SimpleChannelInboundHandler<String> { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.out.println(msg.trim()); } }
12. Netty heartbeat detection mechanism case
Example requirements:
- Write a case of Netty heartbeat detection mechanism. When the server does not read for more than 3 seconds, it will prompt that the read is idle
- When the server has no write operation for more than 5 seconds, it will prompt that the write is idle
- When the server has no read or write operation for more than 7 seconds, it will prompt that the read and write is idle
Startup class:
public static void main(String[] args) throws InterruptedException { NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) //Add log processing Handler for requests in BossGroup .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //Add an IdleStateHandler provided by netty /** * 1,IdleStateHandler It is a processor provided by netty to detect idle state * 2,long readerIdleTime: Indicates how long it has not been read, and a heartbeat detection packet will be sent to detect whether it is still connected * 3,long writerIdleTime: Indicates how long it has not been written, and a heartbeat detection packet will be sent to detect whether it is still connected * 4,long allIdleTime: Indicates how long there has been no reading or writing, and a heartbeat detection packet will be sent to detect whether it is still connected * 5,When the IdleStateEvent is triggered, it will be passed to the next Handler of the pipeline, * Handle this event in the method area by calling (triggering) the userEventTriggered of the next Handler. */ pipeline.addLast(new IdleStateHandler(3, 5, 7, TimeUnit.SECONDS)); //Add a Handler (custom) for further processing of idle detection pipeline.addLast(new MyServerHandler()); } }); //Start the server and set it to synchronization mode. ChannelFuture channelFuture = serverBootstrap.bind(7000).sync(); channelFuture.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
Handler:
public class MyServerHandler extends ChannelInboundHandlerAdapter { /** * @param ctx context * @param evt event * @throws Exception */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { //Transition evt down to IdleStateEvent IdleStateEvent event = (IdleStateEvent)evt; String eventTye = null; switch (event.state()) { case READER_IDLE: eventTye = "Read idle"; break; case WRITER_IDLE: eventTye = "Write idle"; break; case ALL_IDLE: eventTye = "Read write idle"; break; } System.out.println(ctx.channel().remoteAddress() +"---Timeout--" + eventTye); System.out.println("The server will handle it accordingly.."); } } }
13. Netty establishes a Websocket connection
Example requirements:
- Http protocol is stateless. The request between browser and server responds once, and the connection will be re created next time
- Requirements: realize full duplex interaction of long connection based on WebSocket
- Change the constraint of multiple requests of Http protocol to realize a long connection, and the server can send messages to the browser
- The client browser and the server will perceive each other. For example, when the server is closed, the browser will perceive. Similarly, when the browser is closed, the server will perceive
Startup code:
public static void main(String[] args) throws InterruptedException { NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try{ ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //Because it is based on Http protocol, we should use Http encoder and decoder pipeline.addLast(new HttpServerCodec()); //It is written in block mode, and the ChunkedWriter processor is added pipeline.addLast(new ChunkedWriteHandler()); /** * 1,http Data is split during transmission, and HttpObjectAggregator can aggregate multiple segments * 2,This is why when a browser sends a large amount of data, it will issue multiple http requests */ pipeline.addLast(new HttpObjectAggregator(8192)); /** * 1,For websocket, its data is transmitted in the form of frames * 2,You can see that there are six subclasses under the WebsocketFrame * 3,When requested by the browser: ws://localhost:7000/hello indicates the uri of the request * 4,WebSocketServerProtocolHandler The core function is to upgrade http protocol to ws protocol and maintain long connection * 5,Upgrading from Http protocol to Websocket protocol is switched through StatusCode 101 (Switching Protocols). */ pipeline.addLast(new WebSocketServerProtocolHandler("/hello")); //Custom Handler to handle business logic pipeline.addLast(new MyTextWebSocketFrameHandler()); } }); ChannelFuture sync = serverBootstrap.bind(7000).sync(); sync.channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
Handler
//TextWebSocketFrame represents a text frame public class MyTextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { @Override protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception { System.out.println("The server received a message"+msg.text()); //Reply message ctx.channel().writeAndFlush(new TextWebSocketFrame("Server time"+ LocalDateTime.now()+" "+msg.text())); } //This method is triggered when the web client connects @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { //id is a unique value, LongText is unique, and shortText is not unique System.out.println("handlerAdded Called"+ctx.channel().id().asLongText()); System.out.println("handlerAdded Called"+ctx.channel().id().asShortText()); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { System.out.println("handlerRemoved Called"+ctx.channel().id().asLongText()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("Abnormal occurrence"+cause.getMessage()); ctx.close(); } }
14. Case summary
Create startup class:
- First initialize two nioeventloopgroups. BossGroup generally sets the thread to 1
- Initialize a ServerBootStrap class. And call it to set many parameters.
- group(): set two groups for the server and one group for the client
- chnnel(): the server passes in NioServerSocketChannel and the client passes in NioSocketChannel
- option(): the server sets so to BossGroup_ Backlog task queue size
- childOption(): the server sets the connection so for the WorkerGroup_ Keepalive keep connected
- handler(): the server sets handler for BossGroup and the client sets handler
- childHandler(): the server sets the Handler for the WorkerGroup.
- Bind the port through BootStrap and listen for shutdown events. Set to sync
Handler:
- SimpleChannelInboundHandler: it can be inherited to handle many communications. After the deliberation of the above cases, it is common to write your own Handler to inherit it
- ChannelInboundHandlerAdapter: This is the parent class of the previous one. We can judge the connection status by inheriting its userEventTriggered during heartbeat detection. We can also inherit this trigger through the simple above
- IdleStateHandler: during heartbeat detection, we need to trigger the above trigger through this Handler
- HttpServerCodec: provides good for Http encoding and decoding, which is generally used for Http requests
- ChunkedWriteHandler: provide a good Handler, write in block mode, and add a ChunkedWriter processor, which is generally used to send large files.
- HttpObjectAggregator: it aggregates http data and sends it together
- WebSocketServerProtocolHandler: pass in the ws path and upgrade the Http protocol to ws protocol
Communication data entity in Netty:
- TextWebSocketFrame: This is used when websocket is connected. It represents a text frame and is the data form of websocket communication
- HttpObject: This is used when establishing an Http connection. It can be converted into an HttpRequest
Common methods of handler:
Method name | introduce |
---|---|
channelRead0(ChannelHandlerContext channelHandlerContext, T t) | Read the data and forward the message |
handlerAdded(ChannelHandlerContext ctx) | The connection is established. Once the connection is established, it is executed first |
channelActive(ChannelHandlerContext ctx) | Indicates that the channel is active and prompts xxx to go online |
channelInactive(ChannelHandlerContext ctx) | Indicates that the channel is inactive, prompting xxx to go offline |
handlerRemoved(ChannelHandlerContext ctx) | Indicates that the channel is disconnected and pushes xx customer's departure information to the current online customer |
exceptionCaught(ChannelHandlerContext ctx, Throwable cause) | How to handle errors |
userEventTriggered(ChannelHandlerContext ctx, Object evt) | Event trigger: judge what event happened by judging the type of evt, and then judge the type of event through the attributes inside. We add a trigger after IdleStateHandler to detect heartbeat. |