java通过netty实现心跳机制_Netty4服务端心跳机制
Netty4與Netty3.x的心跳機制略有不同,在Netty4中已經去掉了IdleStateAwareChannelHandler這個類,但IdleStateHandler依舊保留,只是心跳超時的觸發事件的寫法略有不同,Netty底層實現了一套類似信號和槽的事件通信機制。
這里且看實現。
首先是在 SocketChannel.pipeline 中注冊 IdleStateHandler 進行心跳時間的定制:
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
// Configure the server.
EventLoopGroup bossGroup?=?new?NioEventLoopGroup(1);
EventLoopGroup workerGroup?=?new?NioEventLoopGroup();
try?{
ServerBootstrap b?=?new?ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,?100)
.handler(new?LoggingHandler(LogLevel.INFO))
.childHandler(new?ChannelInitializer()?{
@Override
public?void?initChannel(SocketChannel ch)
throwsException{
ch.pipeline()
.addLast(
new?LoggingHandler(LogLevel.INFO),
new?IdleStateHandler(30,0,0),// 心跳控制
new?ServerHandler());
}
});
// Start the server.
ChannelFuture f?=?b.bind(port).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
}?catch?(InterruptedExceptione)?{
e.printStackTrace();
}?finally?{
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
這里要注意IdleStateHandler()要放在ServerHandler()的前面,否則心跳管理無法觸發ServerHandler中的userEventTriggered()方法。
此時已經成功在服務器中創建了心跳控制器:
IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds)
Property
Meaning
readerIdleTime
anIdleStateEventwhose state isIdleState.READER_IDLEwill be triggered when no read was performed for the specified period of time. Specify?0to disable.
writerIdleTime
anIdleStateEventwhose state isIdleState.WRITER_IDLEwill be triggered when no write was performed for the specified period of time. Specify?0?to disable.
allIdleTime
anIdleStateEventwhose state isIdleState.ALL_IDLEwill be triggered when neither read nor write was performed for the specified period of time. Specify?0?to disable.
這里readerIdleTime為讀超時時間(即服務器一定時間內未接受到客戶端消息)
writerIdleTime為寫超時時間(即服務器一定時間內向客戶端發送消息)
allIdleTime為全體超時時間(即同時沒有讀寫的時間)
對于以上幾種Time的使用根據用戶自己的需求來決定。這里我們作為驗證客戶端心跳的機制,只需要設置readerIdleTime這一個參數就夠了。
接下來我們需要在ServerHandler中實現其繼承自ChannelInboundHandlerAdapter的userEventTriggered()方法來做心跳超時事件的觸發實現,代碼如下
ServerHandler.java
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
public?class?ServerHandler?extends?ChannelInboundHandlerAdapter?{
...
@Override
public?void?channelRead(ChannelHandlerContext ctx,Objectmsg)
throwsException{
...
}
...
@Override
public?void?userEventTriggered(ChannelHandlerContext ctx,Objectevt)
throwsException{
/*心跳處理*/
if?(evt?instanceof?IdleStateEvent)?{
IdleStateEvent event?=?(IdleStateEvent)?evt;
if?(event.state()?==?IdleState.READER_IDLE)?{
/*讀超時*/
System.out.println("READER_IDLE 讀超時");
ctx.disconnect();
}?else?if?(event.state()?==?IdleState.WRITER_IDLE)?{
/*寫超時*/
System.out.println("WRITER_IDLE 寫超時");
}?else?if?(event.state()?==?IdleState.ALL_IDLE)?{
/*總超時*/
System.out.println("ALL_IDLE 總超時");
}
}
}
}
@Override
public?void?channelInactive(ChannelHandlerContext ctx)?throwsException{
// 這里加入玩家的掉線處理
ctx.close();
}
...
通過對IdleStateEvent的判斷即可分別實現不同超時情況的處理,這里我們針對的是READER_IDLE的超時判斷,因此在其判斷成功后執行ctx.disconnect(),即關閉客戶端連接。
此時會觸發channelInactive()方法,我們將玩家的斷線處理如保存玩家信息等內容寫在channelInactive()中即可。
客戶端主動斷開的連接同理,均會觸發其Channel所屬的Handler中的channelInactive()方法。
以上即實現了一套簡單的服務器心跳機制,只要保證客戶端在每單位時間(這里設置的是30秒)發送一次消息給服務器即可保證其不被踢下線。
本篇到此,歡迎大家提出更優化的心跳機制實現方案。
謝謝關注。
轉自:BeiTown's Coder 編碼之源http://coder.beitown.com/archives/1180
這里也可以參考:http://blog.csdn.net/educast/article/details/47706863
評論
暫無評論!
昵??稱:
驗證碼:
內??容:
打賞
微信掃一掃,打賞一下~
關注公眾號
總結
以上是生活随笔為你收集整理的java通过netty实现心跳机制_Netty4服务端心跳机制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 批量采集发布自媒体文章到wp等博客网站
- 下一篇: DICOM3.0中的VR相关介绍