因为DotNetty是从java的Netty框架仿写过来的,介绍的文档特别少,加之官方也没有提供api文档,所以之前一直不理解心跳的用法。最近忙里偷闲,稍稍研究了一番,终于有点明白了。
现在将代码复制上来,留作日后查看(ps:精髓都在代码里):
Uptime.Client:
public class Program { const string HOST = "127.0.0.1"; const int PORT = 8045; // Sleep 5 seconds before a reconnection attempt. public const int RECONNECT_DELAY = 5; // Reconnect when the server sends nothing for 10 seconds. private const int READ_TIMEOUT = 10; private static UptimeClientHandler handler = new UptimeClientHandler(); private static Bootstrap bs = new Bootstrap(); static void Main(string[] args) { EventLoopGroup group = new EventLoopGroup(); bs.Group(group) .Channel<TcpSocketChannel>() .RemoteAddress(HOST, PORT) .Handler(new ActionChannelInitializer<ISocketChannel>(channel => { //IdleStateHandler心跳检测处理器,添加自定义处理Handler类实现userEventTriggered()方法作为超时事件的逻辑处理 //IdleStateHandler心跳检测每十秒进行一次读检测,如果十秒内ChannelRead()方法未被调用则触发一次userEventTrigger()方法. IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast(new IdleStateHandler(READ_TIMEOUT, 0, 0), handler);//第一个参数为读,第二个为写,第三个为读写全部 })); } }
Uptime.Client.UptimeClientHandler:
public class UptimeClientHandler : SimpleChannelInboundHandler<object> { long startTime = -1; //ChannelActive:活跃状态,可接收和发送数据 public override void ChannelActive(IChannelHandlerContext ctx) { if (startTime < 0) { startTime = GetTimeStamp(); } Console.WriteLine("Connected to: " + ctx.Channel.RemoteAddress); } protected override void ChannelRead0(IChannelHandlerContext context, object message) { var byteBuffer = message as IByteBuffer; if (byteBuffer != null) { Console.WriteLine("Received from server: " + byteBuffer.ToString(Encoding.UTF8)); } context.WriteAsync(message); } public override void UserEventTriggered(IChannelHandlerContext ctx, object evt) { if (!(evt is IdleStateEvent)) { return; } IdleStateEvent e = evt as IdleStateEvent; if (e.State == IdleState.ReaderIdle) { // The connection was OK but there was no traffic for last period. Console.WriteLine("Disconnecting due to no inbound traffic"); ctx.CloseAsync(); } } //channelInactive: 处于非活跃状态,没有连接到远程主机。 public override void ChannelInactive(IChannelHandlerContext context) { Console.WriteLine("Disconnected from: " + context.Channel.RemoteAddress); } //channelUnregistered: 已创建但未注册到一个 EventLoop。 public override void ChannelUnregistered(IChannelHandlerContext context) { } public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) { Console.WriteLine("Exception: " + exception); context.CloseAsync(); } /// <summary> /// 获取时间戳 /// </summary> /// <returns></returns> private long GetTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalMilliseconds); } }
Uptime.Server:
class Program { private static readonly int PORT = 8045; private static readonly UptimeServerHandler handler = new UptimeServerHandler(); static void Main(string[] args) => RunServerAsync().Wait(); static async Task RunServerAsync() { IEventLoopGroup bossGroup = new MultithreadEventLoopGroup(1); IEventLoopGroup workerGroup = new MultithreadEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.Group(bossGroup, workerGroup) .Channel<TcpServerSocketChannel>() .Handler(new LoggingHandler("SRV-LSTN")) .ChildHandler(new ActionChannelInitializer<IChannel>(channel => { //工作线程连接器 是设置了一个管道,服务端主线程所有接收到的信息都会通过这个管道一层层往下传输 //同时所有出栈的消息也要这个管道的所有处理器进行一步步处理 IChannelPipeline pipeline = channel.Pipeline; pipeline.AddLast("Uptime", handler); })); // Bind and start to accept incoming connections. IChannel boundChannel = await b.BindAsync(PORT); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully // shut down your server. await boundChannel.CloseAsync(); } finally { await Task.WhenAll( bossGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1)), workerGroup.ShutdownGracefullyAsync(TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1))); } } }
Uptime.Server.UptimeServerHandler:
public class UptimeServerHandler : SimpleChannelInboundHandler<object> { protected override void ChannelRead0(IChannelHandlerContext ctx, object msg) { // discard } //捕获 异常,并输出到控制台后断开链接,提示:客户端意外断开链接,也会触发 public override void ExceptionCaught(IChannelHandlerContext context, Exception exception) { Console.WriteLine("Exception: " + exception); context.CloseAsync(); } }
最后,附上参考文档链接:DotNetty系列三:编码解码器,IdleStateHandler心跳机制,群发
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232262.html原文链接:https://javaforall.net
