1

Introduction

In the era of rapid increase in Internet speed, browsers have become our entrance to various services. It is difficult to imagine how our online world should function if we leave the browser. Now I can't wait to put the operating system on the browser. But not all applications require a browser to execute. For example, communication between a server and a server requires the use of a self-built client to interact with the server.

This article will introduce the principle and specific implementation of using netty client to connect to websocket.

Browser client

Before introducing the netty client, let’s look at a simple example of a browser client connecting to websocket:

// 创建连接
const socket = new WebSocket('ws://localhost:8000');

// 开启连接
socket.addEventListener('open', function (event) {
    socket.send('没错,开启了!');
});

// 监听消息
socket.addEventListener('message', function (event) {
    console.log('监听到服务器的消息 ', event.data);
});

The browser's most common language javascript is used here, and the websocket API provided by the browser is used for operation, which is very simple.

So is using netty client to realize websocket connection the same as using javascript? Let's explore together.

Netty support for websocket client

Let's take a look at the netty support classes for websocket, and then let's see how to use these tools.

WebSocketClientHandshaker

Like websocket server, the core class in client is also handshaker, which is called WebSocketClientHandshaker here. What does this class do? Lets come look.

This class mainly implements the handshake between client and server.

Let's take a look at its longest parameter construction class:

   protected WebSocketClientHandshaker(URI uri, WebSocketVersion version, String subprotocol,
                                        HttpHeaders customHeaders, int maxFramePayloadLength,
                                        long forceCloseTimeoutMillis, boolean absoluteUpgradeUrl) 

There is the URI of the websocket connection in the parameter, such as: "ws://flydean.com/mypath".

There are request subprotocol type subprotocol, custom HTTP headers: customHeaders, maximum frame payload length: maxFramePayloadLength, mandatory timeout closing time, and URI address for upgrading using HTTP protocol.

How to create a handshaker? Similarly, netty provides a WebSocketClientHandshakerFactory method.

WebSocketClientHandshakerFactory provides a newHandshaker method, which can easily create various versions of handshaker:

        if (version == V13) {
            return new WebSocketClientHandshaker13(
                    webSocketURL, V13, subprotocol, allowExtensions, customHeaders,
                    maxFramePayloadLength, performMasking, allowMaskMismatch, forceCloseTimeoutMillis);
        }
        if (version == V08) {
            return new WebSocketClientHandshaker08(
                    webSocketURL, V08, subprotocol, allowExtensions, customHeaders,
                    maxFramePayloadLength, performMasking, allowMaskMismatch, forceCloseTimeoutMillis);
        }
        if (version == V07) {
            return new WebSocketClientHandshaker07(
                    webSocketURL, V07, subprotocol, allowExtensions, customHeaders,
                    maxFramePayloadLength, performMasking, allowMaskMismatch, forceCloseTimeoutMillis);
        }
        if (version == V00) {
            return new WebSocketClientHandshaker00(
                    webSocketURL, V00, subprotocol, customHeaders, maxFramePayloadLength, forceCloseTimeoutMillis);
        }

It can be seen that according to the different versions of the incoming protocol, it can be divided into WebSocketClientHandshaker13, WebSocketClientHandshaker08, WebSocketClientHandshaker07, WebSocketClientHandshaker00.

WebSocketClientCompressionHandler

Generally speaking, for the webSocket protocol, in order to improve the transmission performance and speed, and reduce the network bandwidth usage, additional compression and expansion are usually carried in the use process. In order to handle such compression and expansion, netty provides both server-side and client-side support.

For the server, the corresponding handler is called WebSocketServerCompressionHandler, and for the client, the corresponding handler is called WebSocketClientCompressionHandler.

By adding these two handlers to the corresponding pipline, support for the expansion of the compression protocol in websocket can be realized.

There are two levels of protocol extension: permessage-deflate and perframe-deflate, which correspond to PerMessageDeflateClientExtensionHandshaker and DeflateFrameClientExtensionHandshaker, respectively.

As for how to compress it, I won't explain it in detail here, and interested friends can learn about it by themselves.

Netty client processing flow

After explaining netty's support for websocket clients, this section will explain how netty uses these tools for message processing.

The first is to create the client's Bootstrap according to the normal logic and add a handler. The handler here is a client-side handler customized for websocket.

In addition to the WebSocketClientCompressionHandler mentioned above, it is a custom handler.

In the custom handler, we need to deal with two things, one thing is to create a handshaker when the channel is ready. Another thing is the processing of specific websocket messages.

Create handshaker

First use WebSocketClientHandshakerFactory to create a handler:

TestSocketClientHandler handler =
     new TestSocketClientHandler(
        WebSocketClientHandshakerFactory.newHandshaker(
              uri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders()));

Then use handshaker for handshake connection when the channel is active:

    public void channelActive(ChannelHandlerContext ctx) {
        handshaker.handshake(ctx.channel());
    }

Then when the message is received, it is necessary to determine whether the status of the handshaker is complete. If it is not completed, call the handshaker.finishHandshake method to complete it manually:

        if (!handshaker.isHandshakeComplete()) {
            try {
                handshaker.finishHandshake(ch, (FullHttpResponse) msg);
                log.info("websocket Handshake 完成!");
                handshakeFuture.setSuccess();
            } catch (WebSocketHandshakeException e) {
                log.info("websocket连接失败!");
                handshakeFuture.setFailure(e);
            }
            return;
        }

When the handshake is completed, normal websocket message read and write operations can be performed.

Websocket message processing

The message processing of websocket is relatively simple, just convert the received message into a WebSocketFrame for processing.

        WebSocketFrame frame = (WebSocketFrame) msg;
        if (frame instanceof TextWebSocketFrame) {
            TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
            log.info("接收到TXT消息: " + textFrame.text());
        } else if (frame instanceof PongWebSocketFrame) {
            log.info("接收到pong消息");
        } else if (frame instanceof CloseWebSocketFrame) {
            log.info("接收到closing消息");
            ch.close();
        }

Summarize

This article explains the websocket client support provided by netty and the specific docking process. You can expand on the basis again to implement your own business logic.

For the examples in this article, please refer to: learn-netty4

This article has been included in http://www.flydean.com/25-netty-websocket-client/

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!


flydean
890 声望433 粉丝

欢迎访问我的个人网站:www.flydean.com