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
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
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
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