Netty: WebSocket application, code demo

WebSocket

Why use the advanced version? The new technology must have solved the technical problem

Defects of Http protocol:

The communication can only be initiated by the client, which requires a kind of ability that the server can actively push to - websocket

**websocket: * * this is a two-way communication capability, also known as "full duplex"

websocket is initiated by the browser

Generally, we use http to call short connection better

websocket is called: long connections are more reusable

Applicable to different scenarios

Here, we still use http to link, but after connecting, we transmit information until it is disconnected

In essence, the bottom layer of http is tcp, which supports full duplex

Protocol identifier http://127.0.0.1:8080 ws://127.0.0.1:7777

GET ws://127.0.0.1:7777 HTTP/1.1
Host: 127.0.0.1
Upgrade: websocket    # Upgrade to ws   
Connection: Upgrade   # This link needs to be upgraded
Sec-WebSocket-key: client-random-string ...  # Identify encryption related information

Response results

HTTP/1.1 101
Upgrade: websocket
Connection: Upgrade

The response code 101 indicates that the protocol needs to be changed to websocket

After the connection is established, text information and binary information are supported.

Principle of Websocket implementation:
Establish the connection (handshake and answer) through http protocol. After establishing the connection, http is no longer used. tcp itself supports two-way communication, so it can achieve the effect of "full duplex".

Websocket Application demo

Server code

public class WebSocketServer {
    public static void main(String[] args) {
        //You can customize the number of threads
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        // Number of threads created by default = number of CPU processors * 2
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler())
                //When the current connection is blocked, the BACKLOG represents the length of the event blocking queue
                .option(ChannelOption.SO_BACKLOG, 128)
                //Set the connection to remain active
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childHandler(new WebSocketInitialzer());

        try {
            ChannelFuture future = serverBootstrap.bind(7777).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

Server initializer

public class WebSocketInitialzer extends ChannelInitializer<Channel> {
    @Override
    protected void initChannel(Channel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //Another way to add codecs
        pipeline.addLast(new HttpServerCodec());
        //    The processor written in block mode is suitable for processing big data
        pipeline.addLast(new ChunkedWriteHandler());
        //polymerization
        pipeline.addLast(new HttpObjectAggregator(512 * 1024));
        /*
         * At this time, we need to declare that we are using the websocket protocol
         * netty The corresponding processor is also prepared for websocket, and the access path is set
         * At this time, we only need to visit ws://127.0.0.1:7777/hello
         * This handler upgrades the http protocol to websocket and uses 101 as the response code
         * */
        pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
        pipeline.addLast(new WebSocketHandler());
    }
}

Server processor

The unit used for communication is called frame
Client: cut the message into multiple frames when sending
Server: reassemble the associated frames when receiving

/*
 * Generics represent units that process data
 * TextWebSocketFrame : Text information frame
 * */
public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame textWebSocketFrame) throws Exception {
        //You can directly call text to get the information in the text information frame
        System.out.println("msg:" + textWebSocketFrame.text());
        Channel channel = ctx.channel();
        //We can create a new object and put the information that the server needs to return into it
        TextWebSocketFrame resp = new TextWebSocketFrame("hello client from websocket server");
        channel.writeAndFlush(resp);
    }
}

Writing websocket front end

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    var socket;
    //    Judge whether the current browser supports websocket
    if (!window.WebSocket) {
        alert("I won't support it websocket")
    } else {
        <!-- establish websocket Connection object-->
        socket = new WebSocket("ws://127.0.0.1:7777/hello");
        //Set the method to start the connection
        socket.onopen = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = "The connection has been opened";
        }
        //Set the method to close the connection
        socket.onclose = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = tmp.value + "\n" + "The connection has been closed";
        }
        //Set the method of receiving data
        socket.onmessage = function (ev) {
            var tmp = document.getElementById("respText");
            tmp.value = tmp.value + "\n" + ev.data;
        }
    }

    function send(message) {
        if (!window.socket) {
            return
        }
        /*
        * Judge the state of socket
        * connecting Connecting closing closing
        * closed Failed to close or open connection
        * open The connection can communicate normally
        * */
        if (socket.readyState == WebSocket.OPEN) {
            socket.send(message);
        } else {
            alert("Connection not open");
        }
    }
</script>
<!--Prevent automatic form submission-->
<form onsubmit="return false">
    <textarea name="message" style="height: 400px;width: 400px"></textarea>
    <input type="button" value="send out" onclick="send(this.form.message.value)">
    <textarea id="respText" style="height: 400px;width: 400px"></textarea>
</form>
</body>
</html>

[Client]

var ws = new WebSocket("ws://127.0.0.1:7777/hello");
ws.onopen = function(ev){
     ws.send("hello"); //Send data after establishing connection
}

Design a style
There is a text box on the left and right, with a send button in the middle.
The left text box is used to send data, and the right text box is used to display data.

Demonstration effect

Start service send message

Messages received by the server

Summary

  1. websocket is generally used for reusable connections, and http is generally used for short links
  2. websocket solves the pain point that http connection can only be initiated by the client

Tags: Java Front-end Netty Spring websocket

Posted on Sun, 21 Nov 2021 17:52:54 -0500 by manalnor