Netty With WebSocket
In the last article, we discussed how to use Netty to develop an Http file server, which contains information about how to use Netty provided component classes to parse the Http protocol for processing requests, and then continue to use existing components for encoding and decoding and transmission.
This article is mainly about how to use Netty integration WebSocket to do a DEMO article. In fact, Netty, like Http, provides some handy components for WebSocket encapsulation that you can use just by coding. At this point, I once again experienced Netty’s high scalability.
Then, this article will talk about the content
- What is the
WebSocket
. WebSocket
与Http
The difference between.- Why do we need
WebSocket
. Netty
和WebSocket
Integration between.
What is theWebSocket
That’s how most people describe it
WebSocket is a network technology of full duplex communication between browser and server provided by HTML5.
It’s kind of hard to understand. HTML5 we understand, but full-duplex communication we don’t. So let’s try to figure out what a WebSocket is.
According to our previous study, we know that Socket is a functional interface between the transport layer and the application. Through these interfaces, we can use the TCP/IP protocol stack to send and receive data at the transport layer. So what does WebSocket have to do with this? From the literal meaning of WebSocket, we can split called Web and Socket. Maybe you can GET it, isn’t WebSocket like running on the Web, responsible for the Http Socket communication specification?
I really do! WebSocket is a Socket communication specification based on Http protocol. It provides functions similar to TCP Socket. Like TCP Socket, WebSocket can call the lower protocol stack and send and receive data arbitrarily. But don’t think of WebSocket as an upgrade to Http (for reasons explained below). In fact, WebSocket is a lightweight network communication protocol based on TCP, which is on a par with Http.
Why do we needWebSocket
?
First of all, we need to understand that the emergence of new things in the same field is most likely not to overturn the former, but to continue to improve on the shoulders of giants. The emergence of WebSocket, in fact, is to make up for the shortcomings of Http.
According to WebSocket, we know that it is a network technology of full duplex communication. Http is a half duplex technology. Http has two characteristics under this technology
- Only one-way data flows can be allowed between the client and server at the same time
- The server cannot actively send data to the client, but can only “passively” respond to requests from the client in request-reply mode.
What kind of problems would a half-double bring us? If you’ve ever done real-time messaging, you’re probably more frustrated. Generally speaking, real-time communication requires mutual interaction, that is, you give it to him, he gives it to you. However, it is obvious that half-duplex can only be sent from the client to the server, but not from the server to the client. You might say, well, can’t my client ask the server every once in a while?
In real time, in the absence of Websockets, a “polling” approach is generally used to achieve even communication, that is, continuous requests to the server. If the frequency of polling is high, the effect of real-time communication can be achieved approximately
However, the disadvantages of polling are also obvious, repeatedly sending invalid query requests consumes a lot of bandwidth and CPU resources, which is very uneconomical.
So, WebSocket is full duplex communication.
WebSocket
The characteristics of
Maybe a lot of people have a question: obviously I see WebSocket is based on Http interaction, its protocol format is not similar to Http place? Well, not really. We know that Http is the current Internet communication protocol, there is no other. But WebSocket doesn’t follow a lot of Http. Instead, it has the following features
- First of all,
WebSocket
A binary frame structure is used, withHttp
The structure of is completely different. But in order to be able to facilitate the promotion and application, have to take a “free ride” in the use of habits as far as possibleHttp
Close up. That’s what it’s calledWeb
The meaning of. (I’ll explain why this is hitchhiking below) - Second,
WebSocket
Didn’t likeSocket
useIP + port
But in the same wayHttp
的URI
Format. butURL
The beginning is notHttp
, butws
和wss
, are plaintext and encrypted respectivelyWebSocket
The agreement. - In addition,
WebSocket
The default port is still used80
和443
. Because the current server firewall on the Internet blocks most of the ports, only onHttp
的80
和443
Release, soWebSocket
You cancamouflageintoHttp
Agreement tothroughFirewall, establish a connection with the server.
WebSocket interaction process
While talking about WebSocket features, you may have learned a little bit about WebSocket: WebSocket actually has little to do with Http, but WebSocket thrives on the popularity of Http.
No hurry, let’s take a look at the order of WebSocket interaction. Here is an interactive diagram of the overall picture:
As we have seen, WebSocket also has a TCP handshake process. It first issues an Http Get request, which is detailed below
GET /HTTP/1.1
Upgrader: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Set-WebSocket-Key: sNNdMgdc2VGJEKS
Set-WebSocket-Version: 13
Copy the code
In the message, we should pay attention to several fields
The field name | use |
---|---|
Upgrade |
Set toWebSocket Is required to explain to the serverHttp Upgrade toWebSocket agreement |
Sec-WebSocket-key |
Base64 Encoded 16-byte random number used to verify whetherWebSocket Rather thanHttp agreement |
Sec-WebSocket-Version |
Said the use ofWebSocket Protocol Version number |
Then, when the server receives the packet from the client, it parses the packet. At this point it knows from the message that this is a WebSocket request. Therefore, it starts to construct special message information. The content of the message is
HTTP/1.1 101 Switching Protocols
Upgrader: websocket
Connection: Upgrade
Set-WebSocket-Accept: fFBooB7FAkKLlXgrSz0BT3v4hq5s
Set-WebSocket-Location: ws://examples.com/
Copy the code
The fields of the packet are still familiar. However, we found a description of 101 Switching Protocols, which is a 101 status code returned by the server telling the client that WebSocket full-duplex bidirectional communication is possible. This means that the client and server have agreed to use WebSocket to interact with each other. Http is no longer a problem.
Set-websocket-accept is used to verify the client request message and also to prevent misconnections. This is done by assigning the client set-websocket-key to a dedicated UUID and then calculating the SHA-1 digest. In this case, the client also compares the response information of the server through such calculation to avoid authentication failure.
After the handshake is complete, the subsequent data is no longer Http packets, but binary frames in WebSocket format.
Netty
integrationWebSocket
First again, we use Netty to implement a server startup class
WebSocketServer.java
public class WebSocketServer {
public void run(int port) throws Exception {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch)
throws Exception {
// HTTP decoder
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("http-codec".new HttpServerCodec());
// Is responsible for putting Http information such as version
// Inherits a FullHttpRequesst from the Http content
pipeline.addLast("aggregator".new HttpObjectAggregator(65536));
// Large file write class
ch.pipeline().addLast("http-chunked".new ChunkedWriteHandler());
// WebSocket handles the class
pipeline.addLast("handler".newWebSocketServerHandler()); }});// Listen on the port
Channel ch = b.bind(port).sync().channel();
ch.closeFuture().sync();
} finally{ bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }}public static void main(String[] args) throws Exception {
new WebSocketServer().run(8080); }}Copy the code
Next, we is to realize the processing logic processor WebSocketServerHandler. Java
public class WebSocketServerHandler extends SimpleChannelInboundHandler<Object> {
private static final Logger logger = Logger
.getLogger(WebSocketServerHandler.class.getName());
private WebSocketServerHandshaker handshaker;
@Override
public void messageReceived(ChannelHandlerContext ctx, Object msg)
throws Exception {
// Traditional HTTP access (the handshake process goes here)
if (msg instanceof FullHttpRequest) {
handleHttpRequest(ctx, (FullHttpRequest) msg);
}
/ / the WebSocket connection
else if (msg instanceofWebSocketFrame) { handleWebSocketFrame(ctx, (WebSocketFrame) msg); }}@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
// If HTTP decoding fails, an HHTP exception is returned
if(! req.getDecoderResult().isSuccess() || (!"websocket".equals(req.headers().get("Upgrade")))) {
sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1,
BAD_REQUEST));
return;
}
// Construct the handshake response return, currently the address of the machine
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
"ws://localhost:8080/websocket".null.false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
WebSocketServerHandshakerFactory
.sendUnsupportedWebSocketVersionResponse(ctx.channel());
} else{ handshaker.handshake(ctx.channel(), req); }}private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
// Check whether it is the command to close the link
if (frame instanceof CloseWebSocketFrame) {
handshaker.close(ctx.channel(),
(CloseWebSocketFrame) frame.retain());
return;
}
// Check whether it is a Ping message
if (frame instanceof PingWebSocketFrame) {
ctx.channel().write(
new PongWebSocketFrame(frame.content().retain()));
return;
}
// This routine only supports text messages, not binary messages
if(! (frameinstanceof TextWebSocketFrame)) {
throw new UnsupportedOperationException(String.format(
"%s frame types not supported", frame.getClass().getName()));
}
// Return the reply message
String request = ((TextWebSocketFrame) frame).text();
if (logger.isLoggable(Level.FINE)) {
logger.fine(String.format("%s received %s", ctx.channel(), request));
}
ctx.channel().write(
new TextWebSocketFrame(request
+ ", welcome to Netty WebSocket service, now:
+ new java.util.Date().toString()));
}
private static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) {
// Return the reply to the client
if(res.getStatus().code() ! =200) {
ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(),
CharsetUtil.UTF_8);
res.content().writeBytes(buf);
buf.release();
setContentLength(res, res.content().readableBytes());
}
// If it is not keep-alive, close the connection
ChannelFuture f = ctx.channel().writeAndFlush(res);
if(! isKeepAlive(req) || res.getStatus().code() ! =200) { f.addListener(ChannelFutureListener.CLOSE); }}@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception { cause.printStackTrace(); ctx.close(); }}Copy the code
In fact, the above code is relatively clear. It is mainly divided into two treatments:
methods | instructions |
---|---|
handleHttpRequest() |
Responsible for responding to client handshake requests |
handleWebSocketFrame() |
Responsible for handlingWebSocket The news of the |
While handling handleWebSocketFrame() is responsible for several operations:
- Whether the command is to close the link
- Is it a heartbeat message?
- Whether message content
conclusion
This article was originally intended to talk about Netty and WebSocket integration. But I found that the growth of WebSocket and the reasons behind its popularity are far from as simple as imagined. So I decided to dig a little deeper. Summarize what has been said in the passage
WebSocket
The equivalent ofHttp
A long-link patch for the protocol. It andHttp
Existing commonalities (connection handshake useGet
Request), the first is to solveHttp
The problem of not supporting long connections has been resolvedHttp
Short link features that do not meet requirements.- On the internal structure,
WebSocket
和Http
There are numerous differences. In order to improve efficiency,WebSocket
With binary frames, it is easier to understand and transfer. - use
Netty
Packaged processors can be implemented quicklyWebSocket
The application of
The end!