Exemplo n.º 1
0
        async Task <Result> ProcessAndResponse(
            TcpClient tcpClient,
            Action close_action,
            ZServerChannel channel,
            BerTree request,
            CancellationToken token)
        {
            string name  = "";
            string ip    = "";
            bool   error = false;

            try
            {
                name = channel.GetDebugName(tcpClient);
                ip   = TcpServer.GetClientIP(tcpClient);

                byte[] response = null;
                if (this.ProcessRequest == null)
                {
                    response = await DefaultProcessRequest(channel, request).ConfigureAwait(false);  // 2018/10/10 add configure
                }
                else
                {
                    ProcessRequestEventArgs e = new ProcessRequestEventArgs();
                    e.Request = request;
                    this.ProcessRequest(channel, e);
                    response = e.Response;
                }

                channel.Touch();
                if (token != null && token.IsCancellationRequested)
                {
                    error = true;
                    return(new Result {
                        Value = -1, ErrorInfo = "Cancelled"
                    });
                }

                // 注意调用返回 result.Value == -1 情况下,要及时 Close TcpClient
                Result result = await ZProcessor.SendResponse(response, tcpClient).ConfigureAwait(false); // 2018/10/10 add configure

                channel.Touch();
                if (result.Value == -1)
                {
                    Console.WriteLine("error on response " + name + ": " + result.ErrorInfo);
                    error = true;
                    return(result);
                }

                return(new Result());
            }
            catch (Exception ex)
            {
                if (ex is UnknownApduException ||
                    ex is BadApduException)
                {
                    IpTable.SetInBlackList(ip, TimeSpan.FromHours(1));
                    LibraryManager.Log?.Info(string.Format("IP 地址 {0} 已被加入黑名单,时限一个小时", ip));
                }

                if (channel != null)
                {
                    channel.Close();
                    if (close_action != null)
                    {
                        close_action.Invoke();
                    }
                    LogException(ex, channel, name);
                    channel = null;
                }
                else
                {
                    LogException(ex, channel, name);
                }

                return(new Result {
                    Value = -1, ErrorInfo = "Cancelled"
                });
            }
            finally
            {
                if (error == true &&
                    channel != null)
                {
                    channel.Close();
                    if (close_action != null)
                    {
                        close_action.Invoke();
                    }
                }
            }
        }
Exemplo n.º 2
0
        // Pipeline 版本
        // 处理一个通道的通讯活动
        public async override void HandleClient(TcpClient tcpClient,
                                                Action close_action,
                                                CancellationToken token)
        {
            List <byte> cache = new List <byte>();

            ZServerChannel channel = _tcpChannels.Add(tcpClient, () => { return(new ZServerChannel()); }) as ZServerChannel;

            // 允许对 channel 做额外的初始化
            if (this.ChannelOpened != null)
            {
                this.ChannelOpened(channel, new EventArgs());
            }
            try
            {
                string name = "";
                string ip   = "";

                Task <Result> task = null;
                try
                {
                    name = channel.GetDebugName(tcpClient);
                    ip   = TcpServer.GetClientIP(tcpClient);

                    channel.Touch();

                    int  i       = 0;
                    bool running = true;
                    while (running)
                    {
                        if (token != null && token.IsCancellationRequested)
                        {
                            return;
                        }

                        // 注意调用返回后如果发现返回 null 或者抛出了异常,调主要主动 Close 和重新分配 TcpClient
                        BerTree request = await ZProcessor.GetIncomingRequest(
                            cache,
                            tcpClient,
                            () => channel.Touch()).ConfigureAwait(false);  // 2018/10/10 add configure

                        if (request == null)
                        {
                            Console.WriteLine("client close on request " + i);
                            break;
                        }
                        Console.WriteLine("request " + i);

                        channel.Touch();
                        if (token != null && token.IsCancellationRequested)
                        {
                            return;
                        }

                        // 如果前一轮的任务还没有完成,这里等待
                        if (task != null)
                        {
                            Result result = task.Result;
                            if (result.Value == -1)
                            {
                                return;
                            }
                            task = null;
                        }

                        task = Task.Run(() =>
                                        ProcessAndResponse(
                                            tcpClient,
                                            close_action,
                                            channel,
                                            request,
                                            token));

                        i++;
                    }
                }
                catch (Exception ex)
                {
#if NO
                    if (ex.InnerException != null && ex.InnerException is ObjectDisposedException)
                    {
                        // 这种情况一般是 server 主动清理闲置通道导致的,不记入日志
                    }
                    else if (ex is ObjectDisposedException)
                    {
                        // 这种情况一般是 client close 通道导致,不记入日志
                    }
#endif

#if NO
                    if (GetException(ex, typeof(ObjectDisposedException)) != null)
                    {
                        return;
                    }

                    SocketException socket_ex = (SocketException)GetException(ex, typeof(SocketException));
                    if (socket_ex != null && socket_ex.SocketErrorCode == SocketError.ConnectionReset)
                    {
                        return;
                    }

                    {
                        string strName = "ip:" + ip
                                         + channel == null ? "(null)" : " channel:" + channel.GetHashCode();
                        string strError = strName + " HandleClient() 异常: " + ExceptionUtil.GetExceptionText(ex);
                        LibraryManager.Log?.Error(strError);
                        // Console.WriteLine(strError);
                    }
#endif
                    if (ex is UnknownApduException ||
                        ex is BadApduException)
                    {
                        IpTable.SetInBlackList(ip, TimeSpan.FromHours(1));
                        LibraryManager.Log?.Info(string.Format("IP 地址 {0} 已被加入黑名单,时限一个小时", ip));
                    }

                    LogException(ex, channel, name);
                }
                finally
                {
#if NO
                    outputStream.Flush();
                    outputStream.Close();
                    outputStream = null;

                    inputStream.Close();
                    inputStream = null;
#endif

                    // tcpClient.Close();

                    // 清除全局结果集
                    if (task != null)
                    {
                        // TODO: 要想办法立即终止检索和响应过程
                    }
                }
            }
            finally
            {
                _tcpChannels.Remove(channel);
#if NO
                if (this.ChannelClosed != null)
                {
                    ChannelClosedEventArgs e = new ChannelClosedEventArgs();
                    e.Channel = channel;
                    this.ChannelClosed(channel, e);
                }
#endif
                channel.Close();
                if (close_action != null)
                {
                    close_action.Invoke();
                }
            }
        }