Introduction
In the previous article, we used netty to build a server that can handle the websocket protocol. In this server, we built a special handler to handle HTTP or websocket requests.
Handling two different requests in one handler may be unbearable for some people with code cleanliness. So, is it possible to use different handlers for normal HTTP requests and websocket requests? The answer is yes.
Netty's message processing
We know that all message processing in netty is implemented through handlers. For convenience, netty provides a simple message processing class SimpleChannelInboundHandler. You can override the channelRead0 method by inheriting it:
protected abstract void channelRead0(ChannelHandlerContext ctx, I msg) throws Exception;
Let's look at the definition of SimpleChannelInboundHandler:
public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter
You can see that SimpleChannelInboundHandler itself has a generic I, and this I is the direction we want to explore.
If we want to use this handler to process all messages, then I can take the value of Object.
If we only need to process String messages, we can do this:
public class StringHandler extends
SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String message)
throws Exception {
System.out.println(message);
}
}
Similarly, if you want to process HTTP and WebSocket messages at the same time, you only need to set I to a different type.
For WebSocketFrame, we have:
public class Server2FrameHandler extends SimpleChannelInboundHandler<WebSocketFrame>
For FullHttpRequest, we have:
public class Server2HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest>
Handling WebSocketFrame
For WebSocketFrame messages, we know from the previous section that there are 6 types, namely:
BinaryWebSocketFrame
CloseWebSocketFrame
ContinuationWebSocketFrame
PingWebSocketFrame
PongWebSocketFrame
TextWebSocketFrame
The ones that actually contain content are TextWebSocketFrame and BinaryWebSocketFrame. Here we deal specifically with TextWebSocketFrame:
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
if (frame instanceof TextWebSocketFrame) {
// 将接收到的消息转换成为大写
String request = ((TextWebSocketFrame) frame).text();
ctx.channel().writeAndFlush(new TextWebSocketFrame(request.toUpperCase(Locale.CHINA)));
} else {
String message = "不支持的Frame类型: " + frame.getClass().getName();
throw new UnsupportedOperationException(message);
}
}
Handling HTTP
For the FullHttpRequest in the HTTP request, we just install the normal HTTP service request processing flow.
I will not elaborate here.
Encoder and decoder
Wait, have we forgotten something? Yes, that is the encoder and decoder.
In the previous section, we used WebSocketServerHandshaker to encode and decode websocket messages. But in fact, it is placed in our custom hadler code, which is slightly inelegant to use.
It doesn't matter, netty provides us with a WebSocketServerProtocolHandler class, which is responsible for the encoding and decoding of websocket.
In addition to handling the normal websocket handshake, the WebSocketServerProtocolHandler class also handles the common message types of Close, Ping, and Pong for us. And we only need to focus on the real business logic messages, which is very convenient.
For the remaining Text or Binary frame data, it will be handed over to the next handler in pipline for processing.
Among them, Handshake has two states, namely:
HANDSHAKE_COMPLETE and HANDSHAKE_TIMEOUT.
And HandshakeComplete includes three aspects of information: requestUri, requestHeaders and selectedSubprotocol.
Finally, add WebSocketServerProtocolHandler to the pipeline, and finally get:
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
pipeline.addLast(new Server2HttpHandler());
pipeline.addLast(new Server2FrameHandler());
}
Summarize
A server that separates HTTP requests and webSocket requests is complete. Simple and intuitive is a world pursued by programmers!
For the examples in this article, please refer to: learn-netty4
This article has been included in http://www.flydean.com/24-netty-websocket-server2/
The most popular interpretation, the most profound dry goods, the most concise tutorial, and many tips you don't know are waiting for you to discover!
Welcome to pay attention to my official account: "Program those things", know technology, know you better!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。