public override void ChannelRead(IChannelHandlerContext context, object message)
 {
     SafeProcess(() =>
     {
         var msg = (Message)message;
         if (msg.Type == MessageType.LoginResponse)
         {
             var result = CertifiedResult.FromMessage(msg);
             if (result.IsOK)
             {
                 //认证成功
                 Online(context);
                 context.FireChannelRead(msg);
             }
             else
             {
                 //认证失败
                 ClientEvents.AsyncRaiseError(this.Client, new LoginFailedException(result.Info));
                 context.CloseAsync();
             }
         }
         else
         {
             //不是登录认证的响应,那么交由下一个通道处理器
             context.FireChannelRead(msg);
         }
     }, context);
 }
        public override void ChannelRead(IChannelHandlerContext context, object message)
        {
            SafeProcess(() =>
            {
                var msg = (Message)message;
                if (msg.Type == MessageType.LoginResponse)
                {
                    DisposeCancellation();
                    _heartBeatCancellation = new CancellationTokenSource();
                    //得到登录响应后,开始心跳
                    context.Executor.ScheduleAsync(RunHeartBeat, context, _delay, _heartBeatCancellation.Token);
                }
                else if (msg.Type == MessageType.HeartBeatResponse)
                {
                    //得到回复后继续心跳
                    context.Executor.ScheduleAsync(RunHeartBeat, context, _delay, _heartBeatCancellation.Token);

                    ClientEvents.AsyncRaiseHeartBeatReceived(this.Client, this.Client.ServerEndPoint);
                }
                else
                {
                    context.FireChannelRead(message);
                }
            }, context);
        }
Ejemplo n.º 3
0
        internal void AddOrUpdateParticipant(Participant participant)
        {
            lock (_participants)
            {
                if (!_participants.ContainsKey(participant.Id))
                {
                    _participants.Add(participant.Id, participant);
                    ClientEvents.AsyncRaiseParticipantAdded(this.Client, this, participant, IsLocal(participant));
                }
                else
                {
                    _participants[participant.Id] = participant;
                    ClientEvents.AsyncRaiseParticipantUpdated(this.Client, this, participant, IsLocal(participant));
                }

                if (!string.IsNullOrEmpty(participant.Orgin))
                {
                    if (!_participantsForOrigin.ContainsKey(participant.Orgin))
                    {
                        _participantsForOrigin.Add(participant.Orgin, participant);
                    }
                    else
                    {
                        _participantsForOrigin[participant.Orgin] = participant;
                    }
                }


                //exist.LastActiveTime = DateTime.Now; //更新最后一次活跃时间
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// 会话上线
 /// </summary>
 /// <param name="session"></param>
 /// <param name="package"></param>
 protected void Online(IChannelHandlerContext ctx)
 {
     this.Client.Status  = ConnectionStatus.Connected;
     this.Client.Channel = ctx.Channel;                                         //原本是不需要再这里设置的,但是在一些很偶然的情况下,
                                                                                //我们发现通过Channel = bootstrap.ConnectAsync(this.ServerEndPoint).Result;
                                                                                //会比这里更加晚执行,导致Channel为null
                                                                                //所以此处手动赋值一次
     ClientEvents.AsyncRaiseConnected(this.Client, this.Client.ServerEndPoint); //触发已连接的事件
 }
Ejemplo n.º 5
0
 protected void SafeProcess(Action action, IChannelHandlerContext context)
 {
     try
     {
         action();
     }
     catch (Exception ex)
     {
         Offline(context);
         ClientEvents.AsyncRaiseError(this.Client, ex);
     }
 }
Ejemplo n.º 6
0
        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            SafeProcess(() =>
            {
                if (Util.OfflineHandle(context, exception))
                {
                    return;
                }

                ClientEvents.AsyncRaiseError(this.Client, exception);
                context.FireExceptionCaught(exception);
            }, context);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 重连
        /// </summary>
        private void _Reconnect(ReconnectArgs arg)
        {
            DisposeReconnectCancellation();

            if (this.Config.ReconnectTimes > 0 && arg.Times == this.Config.ReconnectTimes)
            {
                //this.Config.ReconnectTimes小于或者等于0的时候,不触发错误,因为无限重连
                ClientEvents.AsyncRaiseError(this, new ReconnectFailedException());
                return;
            }

            arg.Times++;
            _Connect(arg);
        }
Ejemplo n.º 8
0
        internal void RemoveParticipant(Participant participant)
        {
            lock (_participants)
            {
                if (_participants.Remove(participant.Id))
                {
                    ClientEvents.AsyncRaiseParticipantRemoved(this.Client, this, participant, IsLocal(participant));
                }

                if (!string.IsNullOrEmpty(participant.Orgin))
                {
                    _participantsForOrigin.Remove(participant.Orgin);
                }
            }
        }
Ejemplo n.º 9
0
        private void _Disconnect(bool isDropped)
        {
            if (_disposed)
            {
                return;
            }
            if (this.Status != ConnectionStatus.Connected)
            {
                return;
            }
            this.Status = ConnectionStatus.Disconnected;

            try
            {
                DisposeReconnectCancellation();

                if (Channel != null)
                {
                    this.LeaveAll();
                    _DisposeChannel();
                    ClientEvents.AsyncRaiseDisconnected(this, isDropped);
                }
            }
            catch (Exception ex)
            {
                ClientEvents.AsyncRaiseError(this, ex);
            }
            finally
            {
                if (isDropped)
                {
                    _pipeline.Queue(() =>
                    {
                        _Reconnect(new ReconnectArgs());
                    });
                }
            }
        }
Ejemplo n.º 10
0
 private void ReceivedMessage(Message message)
 {
     //触发接收消息的事件
     ClientEvents.AsyncRaiseMessageReceived(this.Client, message);
 }
Ejemplo n.º 11
0
        /// <summary>
        /// 连接
        /// </summary>
        /// <returns></returns>
        private void _Connect(ReconnectArgs reconnectArgs)
        {
            if (_disposed)
            {
                return;
            }
            if (this.Status != ConnectionStatus.Disconnected)
            {
                return;
            }
            this.Status = ConnectionStatus.Connecting;

            if (_group == null)
            {
                _group = new MultithreadEventLoopGroup();
            }

            X509Certificate2 cert       = null;
            string           targetHost = null;

            if (this.Config.IsSsl)
            {
                cert       = new X509Certificate2(Path.Combine(AppContext.ProcessDirectory, "anycast.pfx"), "password");
                targetHost = cert.GetNameInfo(X509NameType.DnsName, false);
            }

            var bootstrap = new Bootstrap();

            bootstrap
            .Group(_group)
            .Channel <TcpSocketChannel>()
            .Option(ChannelOption.TcpNodelay, true)
            .Option(ChannelOption.Allocator, UnpooledByteBufferAllocator.Default)     //由于断线重连有内存泄露问题,所以我们使用 非池的字节缓冲区
            .Handler(new ActionChannelInitializer <ISocketChannel>(channel =>
            {
                IChannelPipeline pipeline = channel.Pipeline;

                if (cert != null)
                {
                    pipeline.AddLast("tls", new TlsHandler(stream => new SslStream(stream, true, (sender, certificate, chain, errors) => true), new ClientTlsSettings(targetHost)));
                }
                pipeline.AddLast(new LoggingHandler());
                pipeline.AddLast("framing-enc", new MessageEncoder());
                pipeline.AddLast("framing-dec", new MessageDecoder());

                pipeline.AddLast("ReadTimeout", new ReadTimeoutHandler(Settings.Timeout));     //超过指定时间没有接收到任何信息,自动关闭
                pipeline.AddLast("LoginAuthReq", new LoginAuthReqHandler(this));
                pipeline.AddLast("HeartBeatReq", new HeartBeatReqHandler(this));
                pipeline.AddLast("ClientLogic", new ClientLogicHandler(this));
            }));

            this.ServerEndPoint = new IPEndPoint(IPAddress.Parse(this.Config.Host), this.Config.Port);
            ClientEvents.AsyncRaiseConnecting(this, reconnectArgs);

            try
            {
                if (reconnectArgs != null && reconnectArgs.Times > 0)  //第0次重连意味着是直接连接,不用等待
                {
                    _reconnectCancellation = new CancellationTokenSource();
                    Task.Delay(TimeSpan.FromSeconds(this.Config.ReconnectDelayTime), _reconnectCancellation.Token).Wait();
                }

                this.Channel = bootstrap.ConnectAsync(this.ServerEndPoint).Result;
                this.Address = this.Channel.LocalAddress.ToString();  //在client,我们的地址是通道的本地地址

                //while (true)
                //{
                //    this.Channel = bootstrap.ConnectAsync(this.ServerEndPoint).Result;
                //    this.Address = this.Channel.LocalAddress.ToString();  //在client,我们的地址是通道的本地地址
                //    System.Threading.Thread.Sleep(2000);
                //    this.Channel.CloseAsync().Wait();
                //}
            }
            catch (Exception ex)
            {
                this.Status = ConnectionStatus.Disconnected;
                var args = reconnectArgs?.Clone();
                ClientEvents.AsyncRaiseError(this, new ConnectServerException(this.ServerEndPoint, ex, args));
                if (reconnectArgs != null)
                {
                    _pipeline.Queue(() =>
                    {
                        _Reconnect(reconnectArgs);
                    });
                }
            }
        }