zoukankan      html  css  js  c++  java
  • netty 详解(四)netty 开发 WebSocket 长连接程序

     

      WSServer

    package com.oy.ws;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import io.netty.handler.codec.http.HttpObjectAggregator;
    import io.netty.handler.codec.http.HttpServerCodec;
    import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
    import io.netty.handler.stream.ChunkedWriteHandler;
    
    public class WSServer {
        private int port;
        public WSServer(int port) {
            this.port = port;
        }
    
        public static void main(String[] args) {
            new WSServer(8002).run();
        }
    
        public void run() {
            EventLoopGroup boss = new NioEventLoopGroup(1);
            EventLoopGroup work = new NioEventLoopGroup();
    
            try {
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap
                        .group(boss, work)
                        .channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            protected void initChannel(SocketChannel ch) throws Exception {
                                ChannelPipeline pipeline = ch.pipeline();
                                // 因为基于 HTTP 协议,使用 http 的编码解码器
                                pipeline.addLast(new HttpServerCodec());
                                // 以块的方式写
                                pipeline.addLast(new ChunkedWriteHandler());
                                // 因为 http 数据在传输过程中时分段的,HttpObjectAggregator 就可以将多个段聚合
                                pipeline.addLast(new HttpObjectAggregator(8192));
                                // websocket 数据是以帧(frame)的形式传递
                                // webSocketFrame 下面有六个子类
                                // WebSocketServerProtocolHandler:将 http 协议升级为 ws 协议,保持长连接
                                pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
                                pipeline.addLast(new WSServerHandler());
                            }
                        });
    
                // 绑定端口,启动服务
                ChannelFuture future = bootstrap.bind(port).sync();
                System.out.println("server started and listen " + port);
                // 监听关闭
                future.channel().closeFuture().sync();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                boss.shutdownGracefully();
                work.shutdownGracefully();
            }
        }
    }

      

      WSServerHandler

    package com.oy.ws;
    
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
    
    import java.time.LocalDateTime;
    
    /**
     * WebSocketFrame: 表示一个文本帧
     */
    public class WSServerHandler 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()
                    + ", " + msg.text()));
        }
    
        /**
         * 当 web 客户端连接后,触发该方法
         */
        @Override
        public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
            // longText 是唯一的
            System.out.println("handlerAdded 被调用" + ctx.channel().id().asLongText());
            System.out.println("handlerAdded 被调用" + ctx.channel().id().asShortText());
        }
    
        @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 {
            System.out.println("发生异常:" + cause.getMessage());
            ctx.close();
        }
    }

      hello.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form onsubmit="return false">
            <textarea name="message" style="height:300px;300px;"></textarea>
            <input type="button" value="发送消息" onclick="send(this.form.message.value)"/>
            <textarea id="responseText" style="height:300px;300px;"></textarea>
            <input type="button" value="清空" onclick="document.getElementById('responseText').value=''"/>
        </form>
    </body>
    <script>
        var socket;
        // 判断当前浏览器是否支持 websocket
        if(window.WebSocket){
            socket = new WebSocket("ws://localhost:8002/hello");
            // ev:收到服务器返回的消息
            socket.onmessage = function (ev) {
                var rt = document.getElementById("responseText");
                rt.value = rt.value + "
    " + ev.data;
            }
    
            // 连接开启
            socket.onopen = function (ev) {
                var rt = document.getElementById("responseText");
                rt.value = "连接开启了";
            }
            // 连接关闭
            socket.onclose = function (ev) {
                var rt = document.getElementById("responseText");
                rt.value = rt.value + "
    " + "连接关闭了";
            }
        } else {
            alert("当前浏览器不支持 WebSocket");
        }
    
        // 客户端发送消息给服务器
        function send(message) {
            // 先判断 socket 是否创建好
            if (!window.socket) {
                return;
            }
            if (socket.readyState == WebSocket.OPEN) {
                // 通过 socket 发送消息
                socket.send(message);
            } else {
                alert("连接失败");
            }
        }
    
    </script>
    </html>

    测试:

      1)启动服务端 WSServer;

      2)启动客户端

     

      3)客户端发送消息给服务器,服务器返回消息给客户端

      ---

  • 相关阅读:
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 梅花桩
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 元音字母辅音字母的数量
    Java 第十一届 蓝桥杯 省模拟赛 最大的元素距离
    Java 第十一届 蓝桥杯 省模拟赛 递增序列
    Java 第十一届 蓝桥杯 省模拟赛 递增序列
    Java 第十一届 蓝桥杯 省模拟赛 最大的元素距离
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/12825111.html
Copyright © 2011-2022 走看看