netty学习笔记之websocket支持

netty对websocket提供协议层面的支持,服务的只需要加上对应的handler即可。

服务端代码:

public class MyServer {
    public static void main(String[] args) {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new WebSocketChannelInitializer());

            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpObjectAggregator(8192));
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));

        pipeline.addLast(new TextWebSocketFrameHandler());
    }
}

public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        System.out.println("收到消息:" + msg.text());

        ctx.channel().writeAndFlush(new TextWebSocketFrame("服务器时间:" + LocalDateTime.now()));
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAdded:" + ctx.channel().id().asLongText());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerRemoved:" + ctx.channel().id().asLongText());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
复制代码

websocket协议是基于http的,客户端直接用前端html代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket客户端</title>
</head>
<body>

    <script type="text/javascript">
        var socket;
        if (window.WebSocket) {
            socket = new WebSocket("ws://localhost:8899/ws");
            socket.onmessage = function (event) {
                var ta = document.getElementById("responseText");
                ta.value = ta.value + "\n" + event.data;
            }

            socket.onopen = function (event) {
                var ta = document.getElementById("responseText");
                ta.value = ta.value + "\n" + "连接开启";
            }

            socket.onclose = function (event) {
                var ta = document.getElementById("responseText");
                ta.value = ta.value + "\n" + "连接关闭";
            }

            function send(message) {
                if(!WebSocket) {
                    return;
                }
                if (socket.readyState == WebSocket.OPEN) {
                    socket.send(message);
                } else {
                    alert("连接尚未开启");
                }
            }

        } else {
            alert('浏览器不支持WebSocket');
        }
    </script>

    <form onsubmit="return false;">
        <textarea name="message" style="width: 400px; height: 200px"></textarea>
        <input type="button" value="发送数据" onclick="send(this.form.message.value)">
        <h3>服务端输出:</h3>
        <textarea id="responseText" style="width: 400px; height: 200px"></textarea>
        <input type="button" onclick="javascript: document.getElementById('responseText').value=''" value="清空内容">
    </form>
</body>
</html>
复制代码

最终效果:

image.png
websocket是全双工协议,服务端可以主动给客户端推送消息:
image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享