WebSocket长连接

PPG007 ... 2021-12-30 About 1 min

# WebSocket长连接

HTTP 传输的是帧,所以泛型都使用 Frame。

服务端:

public class Server {
    public static void main(String[] args) {
        NioEventLoopGroup boss = new NioEventLoopGroup(1);
        NioEventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(boss,worker)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
//                        使用HTTP编码解码器
                        pipeline.addLast(new HttpServerCodec());
//                        以块方式写,添加这个处理器
                        pipeline.addLast(new ChunkedWriteHandler());
//                        HTTP数据分段,这个处理器将多个段聚合
                        pipeline.addLast(new HttpObjectAggregator(8192));
//                        将HTTP协议升级为ws协议获得长连接、匹配url
                        pipeline.addLast(new WebSocketServerProtocolHandler("/ppg"));
                        pipeline.addLast(new TextWebSocketFrameHandler());
                    }
                });
        try {
            ChannelFuture channelFuture = serverBootstrap.bind(8848).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            worker.shutdownGracefully();
            boss.shutdownGracefully();
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

自定义的处理器:

public class TextWebSocketFrameHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("已断开");
//        唯一
        System.out.println(ctx.channel().id().asLongText());
//        不唯一
        System.out.println(ctx.channel().id().asShortText());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println(cause.getMessage());
        ctx.channel().close();
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        System.out.println("已连接");
//        唯一
        System.out.println(ctx.channel().id().asLongText());
//        不唯一
        System.out.println(ctx.channel().id().asShortText());
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        System.out.println("服务器端收到消息"+msg.text());
        ctx.channel().writeAndFlush(new TextWebSocketFrame("时间"+ LocalTime.now()+"\n"+msg.text()));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

前端 HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        let socket;
        if (window.WebSocket){
            socket=new WebSocket('ws://localhost:8848/ppg')
            socket.onmessage=function (ev) {
                let res = document.getElementById('res');
                res.value=res.value+'\n'+ev.data
            }
            socket.onopen=function () {
                let res = document.getElementById('res');
                res.value='连接开启了'
            }
            socket.onclose=function () {
                let res = document.getElementById('res');
                res.value=res.value+'\n连接关闭了'
            }
        }else {
            alert("浏览器不支持WebSocket")
        }
        function send(msg) {
            if (socket.readyState===WebSocket.OPEN){
                socket.send(msg)
            }else {
                alert('未连接')
            }
        }
    </script>
</head>
<body>
<form onsubmit="return false">
    <label>
        <textarea style="height: 300px;width: 300px" name="message"></textarea>
    </label>
    <input type="button" value="发送" onclick="send(this.form.message.value)">
    <label>
        <textarea style="height: 300px;width: 300px" name="res" id="res"></textarea>
    </label>
    <input type="button" value="清空" onclick="document.getElementById('res').value=''">
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Last update: December 30, 2021 10:25
Contributors: PPG007