我是靠谱客的博主 心灵美秋天,这篇文章主要介绍Netty学习----心跳检测机制和WebSocket编程实现服务器和客户端长连接案例(含源码)一. 心跳检测机制案例二. WebSocket编程实现服务器和客户端长连接案例,现在分享给大家,希望可以做个参考。

心跳检测机制和WebSocket编程实现服务器和客户端长连接案例

  • 一. 心跳检测机制案例
  • 二. WebSocket编程实现服务器和客户端长连接案例

一. 心跳检测机制案例

在这里插入图片描述

MyServer 服务端

复制代码
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
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.xizi.netty_heartBeat; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; public class MyServer { public static void main(String[] args) { NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO))//添加一个日志处理器 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //加入一个netty 提供 idleStateHandler /* 1. readerIdTime 表示多长时间没有读的,发送一个心跳检查包 2. writerIdleTime 表示多长时间没有写 3. allIdleTime 表示多长时间没有读写 4. 当IdleStateEvent 触发后 就会传递给管道的下一个handler去处理 通过回调触发下一个handler的userEventTiggered ,在该方法中去处理Event(读/写空闲) */ pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS)); pipeline.addLast(new MyServerHandler()); } }); //启动服务器 ChannelFuture channelFuture = serverBootstrap.bind(7000).sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }

自定义MyServerHandler处理

复制代码
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
package com.xizi.netty_heartBeat; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.timeout.IdleStateEvent; public class MyServerHandler extends ChannelInboundHandlerAdapter { /** * * @param ctx 上下文 * @param evt 事件 * @throws Exception */ @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if(evt instanceof IdleStateEvent){ //将 evt向下转型 IdleStateEvent event=(IdleStateEvent) evt; String evenType=null; switch (event.state()){ case READER_IDLE: evenType="读空闲"; break; case WRITER_IDLE: evenType="写空闲"; case ALL_IDLE: evenType="读写空闲"; break; } System.out.println(ctx.channel().remoteAddress()+"超时事件发送:"+evenType); //出现空闲 关闭通道测试 不会死循环进行 只会读一次 // ctx.channel().close(); } } }

客户端随便启动一个进行测试

出现空闲 关闭通道测试 不会死循环进行 只会进行一次测试,事件空闲看自定义时间

复制代码
1
2
// ctx.channel().close();

在这里插入图片描述

二. WebSocket编程实现服务器和客户端长连接案例

在这里插入图片描述
在这里插入图片描述

页面发送信息进行测试

复制代码
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
47
48
49
50
51
52
53
54
55
56
57
58
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form onsubmit="return false"> <textarea name="message" style="height: 400px;width: 400px"></textarea> <input type="button" value="发送消息" onclick="send(this.form.message.value)" /> <textarea id="responseText" style="height: 400px;width: 400px"></textarea> <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''"/> </form> </body> <script type="text/javascript"> var socket; //判断当前浏览器是否支持websocket编程 if (window.WebSocket) { socket = new WebSocket("ws://localhost:7000/hello"); //收到服务器端回送的消息 socket.onmessage = function (ev) { var rt =document.getElementById("responseText"); rt.value= rt.value+"n"+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+"n"+"连接关闭了....." } } else { alert("当前浏览器不支持websocket"); } //发送消息到服务器 function send(message) { if (!window.socket){ //先判断socket是否创建好 return; } if(socket.readyState==WebSocket.OPEN){ //通过socket 发送消息 socket.send(message); }else { alert("连接没有开启") } } </script> </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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.xizi.websocket; import com.xizi.netty_heartBeat.MyServerHandler; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; 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.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.stream.ChunkedWriteHandler; public class MyServer { public static void main(String[] args) { NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO))//添加一个日志处理器 .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); //基础http协议 使用http解码/编码器 pipeline.addLast(new HttpServerCodec()); //以块方式写,添加CHunkedWritehandler 处理器 pipeline.addLast(new ChunkedWriteHandler()); // 1. http数据传输过程中是分段,HttpObjectAggregator 就是将多个分段聚合起来 // 2. 当数据量很大时候,就会发送多次http请求 pipeline.addLast(new HttpObjectAggregator(8192)); //1. 对应websocket 它的数据是以 帧(frame) 形式传递 //2. 浏览器发送请求 ws://localhost:7000/xxx 表示请求的uri //3. WebSocketServerProtocolHandler 核心功能就是将http协议升级为 ws协议 保持长连接 pipeline.addLast(new WebSocketServerProtocolHandler("/hello")); //自定义的handler 处理业务逻辑 pipeline.addLast(new MyTextWebSocketFrameHandler() ); } }); //启动服务器 ChannelFuture channelFuture = serverBootstrap.bind(7000).sync(); channelFuture.channel().closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } }

自定义MyTextWebSocketFrameHandler 处理器

复制代码
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
package com.xizi.websocket; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import java.time.LocalDate; import java.time.LocalDateTime; public class MyTextWebSocketFrameHandler 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()+"]n消息内容:"+msg.text())); } //当web客户端连接后 触发方法 @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { //id 表示唯一的值 LongText 是唯一的 ShortText 不是唯一的 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("handlerRemove 调用 "+ctx.channel().id().asLongText()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { System.out.println("异常发生 "+cause.getMessage()); ctx.close(); //关闭连接 } }

最后

以上就是心灵美秋天最近收集整理的关于Netty学习----心跳检测机制和WebSocket编程实现服务器和客户端长连接案例(含源码)一. 心跳检测机制案例二. WebSocket编程实现服务器和客户端长连接案例的全部内容,更多相关Netty学习----心跳检测机制和WebSocket编程实现服务器和客户端长连接案例(含源码)一.内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(73)

评论列表共有 0 条评论

立即
投稿
返回
顶部