Exemple #1
0
        // 处理 Server 端可能发来的 Close
        // return value:
        //      -1  error
        //      0   不是Close
        //      1   是Close,已经迫使ZChannel处于尚未初始化状态
        // return InitialResult:
        //      在 InitialResult::ResultInfo 中返回诊断信息
        async Task <InitialResult> CheckServerCloseRequest()
        {
            if (this._channel.Connected == false || this._channel.DataAvailable == false)
            {
                return(new InitialResult()); // 没有发现问题
            }
            // 注意调用返回后如果发现出错,调主要主动 Close 和重新分配 TcpClient
            RecvResult result = await ZChannel.SimpleRecvTcpPackage(this._channel._client, -1).ConfigureAwait(false);

            if (result.Value == -1)
            {
                this.CloseConnection();
                return(new InitialResult {
                    Value = -1, ErrorInfo = result.ErrorInfo
                });
            }

            BerTree tree1 = new BerTree();

            // TODO: 这里需要捕获异常,然后把 Package Dump 到日志文件(base64 形态),便于事后分析调试
            tree1.m_RootNode.BuildPartTree(result.Package,
                                           0,
                                           result.Package.Length,
                                           out int nTotalLen);

            if (tree1.GetAPDuRoot().m_uTag != BerTree.z3950_close)
            {
                // 不是Close
                return(new InitialResult {
                    Value = 0
                });
            }

            CLOSE_REQUEST closeStruct = new CLOSE_REQUEST();
            int           nRet        = BerTree.GetInfo_closeRequest(
                tree1.GetAPDuRoot(),
                ref closeStruct,
                out string strError);

            if (nRet == -1)
            {
                this.CloseConnection();
                return(new InitialResult {
                    Value = -1, ErrorInfo = strError
                });
            }

            this.CloseConnection();
            return(new InitialResult {
                Value = 1, ResultInfo = closeStruct.m_strDiagnosticInformation
            });
        }
Exemple #2
0
        // 处理 Server 端可能发来的 Close
        // return value:
        //      -1  error
        //      0   不是Close
        //      1   是Close,已经迫使ZChannel处于尚未初始化状态
        // return InitialResult:
        //      在 InitialResult::ResultInfo 中返回诊断信息
        async Task <InitialResult> CheckServerCloseRequest()
        {
            if (this._channel.Connected == false || this._channel.DataAvailable == false)
            {
                return(new InitialResult()); // 没有发现问题
            }
            RecvResult result = await this._channel.SimpleRecvTcpPackage();

            if (result.Value == -1)
            {
                return new InitialResult {
                           Value = -1, ErrorInfo = result.ErrorInfo
                }
            }
            ;

            BerTree tree1 = new BerTree();

            tree1.m_RootNode.BuildPartTree(result.Package,
                                           0,
                                           result.Package.Length,
                                           out int nTotalLen);

            if (tree1.GetAPDuRoot().m_uTag != BerTree.z3950_close)
            {
                // 不是Close
                return(new InitialResult {
                    Value = 0
                });
            }

            CLOSE_REQUEST closeStruct = new CLOSE_REQUEST();
            int           nRet        = BerTree.GetInfo_closeRequest(
                tree1.GetAPDuRoot(),
                ref closeStruct,
                out string strError);

            if (nRet == -1)
            {
                return new InitialResult {
                           Value = -1, ErrorInfo = strError
                }
            }
            ;

            this.CloseConnection();
            return(new InitialResult {
                Value = 1, ResultInfo = closeStruct.m_strDiagnosticInformation
            });
        }
Exemple #3
0
        public async Task <RecvResult> SendAndRecv(byte[] baSend)
        {
            {
                Result result = await SimpleSendTcpPackage(this._client,
                                                           baSend,
                                                           baSend.Length).ConfigureAwait(false);

                if (result.Value == -1 || result.Value == 1)
                {
                    this.CloseSocket();
                    return(new RecvResult(result)
                    {
                        Value = -1,
                        //ErrorInfo = result.ErrorInfo,
                        //ErrorCode = result.ErrorCode
                    });
                }
            }

            {
                //byte[] baPackage = null;
                //int nRecvLen = 0;
                // 注意调用返回后如果发现出错,调主要主动 Close 和重新分配 TcpClient
                RecvResult result = await SimpleRecvTcpPackage(this._client, -1).ConfigureAwait(false);

                if (result.Value == -1)
                {
                    this.CloseSocket();
                    return(new RecvResult(result));
                }

#if DEBUG
                if (result.Package != null)
                {
                    Debug.Assert(result.Package.Length == result.Length, "");
                }
                else
                {
                    Debug.Assert(result.Length == 0, "");
                }
#endif

                // this.baRecv = result.Package;
                // this.eventFinished.Set();
                return(result);
            }
        }
Exemple #4
0
        public async Task <RecvResult> SendAndRecv(byte[] baSend)
        {
            {
                Result result = await this.SimpleSendTcpPackage(
                    baSend,
                    baSend.Length);

                if (result.Value == -1 || result.Value == 1)
                {
                    return new RecvResult {
                               Value = -1, ErrorInfo = result.ErrorInfo
                    }
                }
                ;
            }

            {
                //byte[] baPackage = null;
                //int nRecvLen = 0;
                RecvResult result = await this.SimpleRecvTcpPackage();

                if (result.Value == -1)
                {
                    return new RecvResult {
                               Value = -1, ErrorInfo = result.ErrorInfo
                    }
                }
                ;

#if DEBUG
                if (result.Package != null)
                {
                    Debug.Assert(result.Package.Length == result.Length, "");
                }
                else
                {
                    Debug.Assert(result.Length == 0, "");
                }
#endif

                // this.baRecv = result.Package;
                // this.eventFinished.Set();
                return(result);
            }
        }
Exemple #5
0
        // 获得记录
        // 本函数每次调用前,最好调用一次 TryInitialize()
        // 不确保一定可以获得nCount个
        // parameters:
        //		nStart	获取记录的开始位置(从0开始计数)
        public async Task <PresentResult> OncePresent(
            string strResultSetName,
            int nStart,
            int nCount,
            string strElementSetName,
            string strPreferredRecordSyntax)
        {
            if (nCount == 0)
            {
                return new PresentResult {
                           Value = 0, ErrorInfo = "nCount 参数为 0,本次没有真正请求服务器获取记录"
                }
            }
            ;

            BerTree         tree = new BerTree();
            PRESENT_REQUEST struPresent_request = new PRESENT_REQUEST();

            //byte[] baPackage = null;
            //int nRet;

            struPresent_request.m_strReferenceId            = this._currentRefID;
            struPresent_request.m_strResultSetName          = strResultSetName; // "default";
            struPresent_request.m_lResultSetStartPoint      = nStart + 1;
            struPresent_request.m_lNumberOfRecordsRequested = nCount;
            struPresent_request.m_strElementSetNames        = strElementSetName;
            struPresent_request.m_strPreferredRecordSyntax  = strPreferredRecordSyntax;

            int nRet = tree.PresentRequest(struPresent_request,
                                           out byte[] baPackage);

            if (nRet == -1)
            {
                return new PresentResult {
                           Value = -1, ErrorInfo = "CBERTree::PresentRequest() fail!"
                }
            }
            ;
            if (this._channel.Connected == false)
            {
                this.CloseConnection();

                return(new PresentResult {
                    Value = -1, ErrorInfo = "socket尚未连接或者已经被关闭"
                });
            }

#if DUMPTOFILE
            DeleteFile("presentrequest.bin");
            DumpPackage("presentrequest.bin",
                        (char *)baPackage.GetData(),
                        baPackage.GetSize());
            DeleteFile("presentrequest.txt");
            tree.m_RootNode.DumpToFile("presentrequest.txt");
#endif

            BerTree tree1 = new BerTree();

            {
                RecvResult result = await this._channel.SendAndRecv(
                    baPackage);

                if (result.Value == -1)
                {
                    return(new PresentResult(result));
                }

#if DUMPTOFILE
                DeleteFile("presendresponse.bin");
                DumpPackage("presentresponse.bin",
                            (char *)baPackage.GetData(),
                            baPackage.GetSize());
#endif


                tree1.m_RootNode.BuildPartTree(result.Package,
                                               0,
                                               result.Package.Length,
                                               out int nTotalLen);
            }

#if DUMPTOFILE
            DeleteFile("PresentResponse.txt");
            tree1.m_RootNode.DumpDebugInfoToFile("PresentResponse.txt");
#endif
            SEARCH_RESPONSE search_response = new SEARCH_RESPONSE();
            nRet = BerTree.GetInfo_PresentResponse(tree1.GetAPDuRoot(),
                                                   ref search_response,
                                                   out RecordCollection records,
                                                   true,
                                                   out string strError);
            if (nRet == -1)
            {
                return new PresentResult {
                           Value = -1, ErrorInfo = strError
                }
            }
            ;

            SetElementSetName(records, strElementSetName);

            if (search_response.m_diagRecords.Count != 0)
            {
                return new PresentResult {
                           Value = -1, ErrorInfo = "error diagRecords:\r\n\r\n---\r\n" + search_response.m_diagRecords.GetMessage()
                }
            }
            ;

            return(new PresentResult {
                Records = records
            });
        }
Exemple #6
0
        // 检索
        // 本函数每次调用前,最好调用一次 TryInitialize()
        // parameters:
        //      strQuery    Search() 专用的检索式。注意,不是一个检索词那么简单
        //      dbnames     一般是从 targetInfo.DbNames 里面获得。或者从中选择一个数据库名用在这里
        //      strPreferredRecordSyntax 一般是从 targetInfo.PreferredRecordSyntax 获得即可
        // result.Value:
        //		-1	error
        //		0	fail
        //		1	succeed
        // result.ResultCount:
        //      命中结果集内记录条数 (当 result.Value 为 1 时)
        public async Task <SearchResult> Search(
            string strQuery,
            Encoding queryTermEncoding,
            string[] dbnames,
            string strPreferredRecordSyntax,
            string strResultSetName)
        {
            BerTree        tree = new BerTree();
            SEARCH_REQUEST struSearch_request = new SEARCH_REQUEST
            {
                m_dbnames = dbnames
            };

            Debug.Assert(struSearch_request.m_dbnames.Length != 0, "");

            struSearch_request.m_strReferenceId              = this._currentRefID;
            struSearch_request.m_lSmallSetUpperBound         = 0;
            struSearch_request.m_lLargeSetLowerBound         = 1;
            struSearch_request.m_lMediumSetPresentNumber     = 0;
            struSearch_request.m_nReplaceIndicator           = 1;
            struSearch_request.m_strResultSetName            = strResultSetName; // "default";
            struSearch_request.m_strSmallSetElementSetNames  = "";
            struSearch_request.m_strMediumSetElementSetNames = "";
            struSearch_request.m_strPreferredRecordSyntax    = strPreferredRecordSyntax; //  ZTargetControl.GetLeftValue(this.TargetInfo.PreferredRecordSyntax);   // BerTree.MARC_SYNTAX;
            struSearch_request.m_strQuery          = strQuery;
            struSearch_request.m_nQuery_type       = 1;
            struSearch_request.m_queryTermEncoding = queryTermEncoding;


            // m_search_response.m_lErrorCode = 0;
            byte[] baPackage = null;

            try
            {
                // 这里可能抛出异常
                tree.SearchRequest(struSearch_request,
                                   out baPackage);
            }
            catch (Exception ex)
            {
                return(new SearchResult {
                    Value = -1, ErrorInfo = "CBERTree::SearchRequest() Exception: " + ex.Message
                });
            }

            if (this._channel.Connected == false)
            {
                this.CloseConnection();
                return(new SearchResult {
                    Value = -1, ErrorInfo = "socket尚未连接或者已经被关闭"
                });
            }

#if DUMPTOFILE
            string strBinFile = this.MainForm.DataDir + "\\searchrequest.bin";
            File.Delete(strBinFile);
            DumpPackage(strBinFile,
                        baPackage);
            string strLogFile = this.MainForm.DataDir + "\\searchrequest.txt";
            File.Delete(strLogFile);
            tree.m_RootNode.DumpToFile(strLogFile);
#endif


#if NO
            nRet = CheckConnect(
                out strError);
            if (nRet == -1)
            {
                return(-1);
            }
#endif

            BerTree tree1 = new BerTree();

            {
                RecvResult result = await this._channel.SendAndRecv(
                    baPackage);

                if (result.Value == -1)
                {
                    return(new SearchResult(result));
                }

#if NO
#if DEBUG
                if (nRet == 0)
                {
                    Debug.Assert(strError == "", "");
                }
#endif
#endif

#if DUPMTOFILE
                DeleteFile("searchresponse.bin");
                DumpPackage("searchresponse.bin",
                            (char *)baOutPackage.GetData(),
                            baOutPackage.GetSize());
#endif

                tree1.m_RootNode.BuildPartTree(result.Package,
                                               0,
                                               result.Package.Length,
                                               out int nTotalLen);
            }

            SEARCH_RESPONSE search_response = new SEARCH_RESPONSE();
            int             nRet            = BerTree.GetInfo_SearchResponse(tree1.GetAPDuRoot(),
                                                                             ref search_response,
                                                                             true,
                                                                             out string strError);
            if (nRet == -1)
            {
                return new SearchResult {
                           Value = -1, ErrorInfo = strError
                }
            }
            ;

#if DUMPTOFILE
            DeleteFile("SearchResponse.txt");
            tree1.m_RootNode.DumpDebugInfoToFile("SearchResponse.txt");
#endif
            {
                SearchResult result = new SearchResult();

                result.ResultCount = (int)search_response.m_lResultCount;

                if (search_response.m_nSearchStatus != 0)   // 不一定是1
                {
                    result.Value = 1;
                    return(result);
                }

                result.ErrorInfo = "Search Fail: diagRecords:\r\n" + search_response.m_diagRecords.GetMessage();
                result.Value     = 0; // search fail
                return(result);
            }
        }
Exemple #7
0
        // 执行初始化
        // 同步模式
        // parameters:
        //      strResultInfo   [out]返回说明初始化结果的文字
        // return Value:
        //      -1  出错
        //      0   成功
        async Task <InitialResult> Initial(
            TargetInfo targetinfo,
            bool bIgnoreReferenceID,
            string reference_id)
        {
            string strResultInfo = "";

            BerTree      tree             = new BerTree();
            INIT_REQUEST struInit_request = new INIT_REQUEST();

            // TargetInfo targetinfo = connection.TargetInfo;

            if (this._channel.Initialized == true)
            {
                return new InitialResult {
                           Value = -1, ErrorInfo = "先前已经初始化过了,不应重复初始化"
                }
            }
            ;                                                                              // 不能重复调用

            struInit_request.m_strReferenceId = reference_id;
            struInit_request.m_strOptions     = "yynnnnnnnnnnnnnnnn"; // "yyynynnyynynnnyn";

            struInit_request.m_lPreferredMessageSize  = 0x100000;     ////16384;
            struInit_request.m_lExceptionalRecordSize = 0x100000;

            if (String.IsNullOrEmpty(targetinfo.UserName) == false)
            {
                struInit_request.m_strID = targetinfo.UserName;

                struInit_request.m_strPassword           = targetinfo.Password;
                struInit_request.m_strGroupID            = targetinfo.GroupID;
                struInit_request.m_nAuthenticationMethod = targetinfo.AuthenticationMethod;
            }
            else
            {
                struInit_request.m_strID                 = "";
                struInit_request.m_strPassword           = "";
                struInit_request.m_strGroupID            = "";
                struInit_request.m_nAuthenticationMethod = -1;
            }

            struInit_request.m_strImplementationId      = "DigitalPlatform";
            struInit_request.m_strImplementationVersion = "1.2.0";
            struInit_request.m_strImplementationName    = "Z3950_library";

            if (targetinfo.CharNegoUTF8 == true)
            {
                struInit_request.m_charNego = new CharsetNeogatiation();
                struInit_request.m_charNego.EncodingLevelOID          = CharsetNeogatiation.Utf8OID; //  "1.0.10646.1.0.8";   // utf-8
                struInit_request.m_charNego.RecordsInSelectedCharsets = (targetinfo.CharNegoRecordsUTF8 == true ? 1 : 0);
            }

            int nRet = tree.InitRequest(struInit_request,
                                        targetinfo.DefaultQueryTermEncoding,
                                        out byte[] baPackage);

            if (nRet == -1)
            {
                return new InitialResult {
                           Value = -1, ErrorInfo = "CBERTree::InitRequest() fail!"
                }
            }
            ;

            if (this._channel.Connected == false)
            {
                this.CloseConnection();

                return(new InitialResult {
                    Value = -1, ErrorInfo = "socket尚未连接或者已经被关闭"
                });
            }



#if DUMPTOFILE
            DeleteFile("initrequest.bin");
            DumpPackage("initrequest.bin",
                        (char *)baPackage.GetData(),
                        baPackage.GetSize());
            DeleteFile("initrequest.txt");
            tree.m_RootNode.DumpToFile("initrequest.txt");
#endif


            RecvResult result = await this._channel.SendAndRecv(
                baPackage);

            if (result.Value == -1)
            {
                return(new InitialResult(result));
            }

#if DUMPTOFILE
            DeleteFile("initresponse.bin");
            DumpPackage("initresponse.bin",
                        (char *)baOutPackage.GetData(),
                        baOutPackage.GetSize());
#endif

            ////////////////////////////////////////////////////////////////
            BerTree tree1 = new BerTree();
            tree1.m_RootNode.BuildPartTree(result.Package,
                                           0,
                                           result.Package.Length,
                                           out int nTotalLen);


#if DUMPTOFILE
            DeleteFile("InitResponse.txt");
            tree1.m_RootNode.DumpDebugInfoToFile("InitResponse.txt");
#endif

            INIT_RESPONSE init_response = new INIT_RESPONSE();
            nRet = BerTree.GetInfo_InitResponse(tree1.GetAPDuRoot(),
                                                ref init_response,
                                                out string strError);
            if (nRet == -1)
            {
                return new InitialResult {
                           Value = -1, ErrorInfo = strError
                }
            }
            ;


            if (bIgnoreReferenceID == false)
            {
                // 可以帮助发现旧版本dp2zserver的错误
                if (struInit_request.m_strReferenceId != init_response.m_strReferenceId)
                {
                    strError = "请求的 reference id [" + struInit_request.m_strReferenceId + "] 和 响应的 reference id [" + init_response.m_strReferenceId + "] 不一致!";
                    return(new InitialResult {
                        Value = -1, ErrorInfo = strError
                    });
                }
            }

            // 2007/11/5检查version和options
            bool bOption_0 = BerTree.GetBit(init_response.m_strOptions,
                                            0);
            if (bOption_0 == false)
            {
                strError = "服务器响应的 option bit 0 表示不支持 search";

                return(new InitialResult {
                    Value = -1, ErrorInfo = strError
                });
            }

            bool bOption_1 = BerTree.GetBit(init_response.m_strOptions,
                                            1);
            if (bOption_1 == false)
            {
                strError = "服务器响应的 option bit 1 表示不支持 present";
                return(new InitialResult {
                    Value = -1, ErrorInfo = strError
                });
            }

            if (init_response.m_nResult != 0)
            {
                strError = "Initial OK";
            }
            else
            {
                strError = "Initial被拒绝。\r\n\r\n错误码 ["
                           + init_response.m_lErrorCode.ToString()
                           + "]\r\n错误消息["
                           + init_response.m_strErrorMessage + "]";

                strResultInfo = BuildInitialResultInfo(init_response);
                return(new InitialResult
                {
                    Value = -1,
                    ErrorInfo = strError,
                    ResultInfo = strResultInfo
                });
            }

            /*
             * this->m_init_strOption = init_response.m_strOptions;
             * this->m_init_lPreferredMessageSize = init_response.m_lPreferredMessageSize;
             * this->m_init_lExceptionalRecordSize = init_response.m_lExceptionalRecordSize;
             * this->m_init_nResult = init_response.m_nResult;
             * */

            this._channel.Initialized = true;

            // 字符集协商
            if (init_response.m_charNego != null &&
                BerTree.GetBit(init_response.m_strOptions, 17) == true)
            {
                if (init_response.m_charNego.EncodingLevelOID == CharsetNeogatiation.Utf8OID)
                {
                    // 临时修改检索词的编码方式。
                    // 但是还无法反映到PropertyDialog上。最好能反馈。
                    targetinfo.DefaultQueryTermEncoding = Encoding.UTF8;
                    targetinfo.Changed = true;

                    if (init_response.m_charNego.RecordsInSelectedCharsets == 1)
                    {
                        this.ForcedRecordsEncoding = Encoding.UTF8;
                    }
                }
            }

            strResultInfo = BuildInitialResultInfo(init_response);
            return(new InitialResult
            {
                Value = 0,
                ErrorInfo = strError,
                ResultInfo = strResultInfo
            });
        }
Exemple #8
0
        static int DEFAULT_CLEAR_SECONDS = 10;  // TCP 连接后,登录以前,能存活的秒数。超过这个秒数就可能被管理线程 Close 和清除

        // 处理一个通道的通讯活动
        public async override void HandleClient(TcpClient tcpClient,
                                                Action close_action,
                                                CancellationToken token)
        {
            SipChannel channel = _tcpChannels.Add(tcpClient, () => { return(new SipChannel()); }) as SipChannel;

            channel.Timeout = TimeSpan.FromSeconds(DEFAULT_CLEAR_SECONDS);  // 在登录以前,TCP 连接可以存活 DEFAULT_CLEAR_SECONDS 秒。DEFAULT_CLEAR_SECONDS 秒以后还不接到登录请求,TCP 连接会被自动清除。登录后,Timeout 则会被设置为实例参数 AutoClearSeconds 值

            List <byte> cache = new List <byte>();

            try
            {
                string ip = "";

                try
                {
                    ip = GetClientIP(tcpClient);
                    channel.Touch();

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

                        byte[] response = null;

                        {
                            // TODO: 也可以在这里等待多少秒,然后超时以后,条件符合时,自动清除 TCP 通道。可以弥补管理线程轮次不及时的缺点
                            // 注意调用返回后如果发现返回 null 或者抛出了异常,调主要主动 Close 和重新分配 TcpClient
                            RecvResult result = await TcpChannel.SimpleRecvTcpPackage(tcpClient,
                                                                                      cache,
                                                                                      (package, start, length) =>
                            {
                                return(FindTerminator(package, start, length));
                            },
                                                                                      this.MaxPackageLength).ConfigureAwait(false); // 2018/10/10 add configure

                            if (result.Value == -1)
                            {
                                if (result.ErrorCode == "ConnectionAborted")
                                {
                                    Console.WriteLine("client close on request " + i);
                                }
                                else
                                {
                                    Console.WriteLine("recv error on request " + i + ": " + result.ErrorInfo);
                                }
                                break;
                            }
                            channel.Terminator = (byte)result.Terminator;
                            Console.WriteLine("request " + i);

                            // byte [] 转换为 string

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

                            ProcessSipRequestEventArgs e = new ProcessSipRequestEventArgs();
                            e.Request = result.Package;
                            this.ProcessRequest(channel, e);
                            response = e.Response;
                        }

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

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

                            channel.Touch();
                            if (result.Value == -1 || result.Value == 1)
                            {
                                Console.WriteLine("error on response " + i + ": " + result.ErrorInfo);
                                break;
                            }
                        }

                        i++;
                    }
                }
                catch (Exception ex)
                {
                    string strError = "ip:" + ip + " HandleClient() 异常: " + ExceptionUtil.GetExceptionText(ex);
                    LibraryManager.Log?.Error(strError);
                    // Console.WriteLine(strError);
                }
                finally
                {
                    // tcpClient.Close();

                    // 清除全局结果集
                }
            }
            finally
            {
                _tcpChannels.Remove(channel);
                channel.Close();
                if (close_action != null)
                {
                    close_action.Invoke();
                }
            }
        }
Exemple #9
0
        // 接收响应包
        // 注意调用返回后如果发现出错,调主要主动 Close 和重新分配 TcpClient
        // parameters:
        //      nMaxLength  读入等待处理的 bytes 极限数字。超过了这个,还没有找到结束符,就会抛出异常。意在防范攻击。-1 表示不限制
        //      touch_func  回调函数,用于保持通道活跃
        public static async Task <RecvResult> SimpleRecvTcpPackage(TcpClient _client,
                                                                   int nMaxLength,
                                                                   delegate_touch touch_func = null)
        {
            // string strError = "";
            RecvResult result = new RecvResult();

            int  nInLen;
            int  wRet        = 0;
            bool bInitialLen = false;

            Debug.Assert(_client != null, "client为空");

            result.Package = new byte[4096];
            nInLen         = 0;
            result.Length  = 4096; //COMM_BUFF_LEN;

            while (nInLen < result.Length)
            {
                if (_client == null)
                {
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorInfo = "通讯中断"
                    });
                }

                try
                {
                    wRet = await _client.GetStream().ReadAsync(result.Package,
                                                               nInLen,
                                                               result.Package.Length - nInLen).ConfigureAwait(false);

                    touch_func?.Invoke();
                }
                catch (SocketException ex)
                {
                    if (ex.ErrorCode == 10035)
                    {
                        System.Threading.Thread.Sleep(100);
                        continue;
                    }
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorInfo = "recv出错1: " + ex.Message,
                        // "ConnectionAborted"
                        ErrorCode = ((SocketException)ex).SocketErrorCode.ToString()
                    });
                }
                catch (Exception ex)
                {
                    result.Exception = ex;
                    if (ex is IOException && ex.InnerException is SocketException)
                    {
                        // "ConnectionAborted"
                        result.ErrorCode = ((SocketException)ex.InnerException).SocketErrorCode.ToString();
                    }
                    result.ErrorInfo = "recv出错2: " + ex.Message;
                    result.Value     = -1;
                    return(result);
                }

                if (wRet == 0)
                {
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorCode = "Closed",
                        ErrorInfo = "Closed by remote peer"
                    });
                }

                // 得到包的长度

                if ((wRet >= 1 || nInLen >= 1) &&
                    bInitialLen == false)
                {
                    bool bRet = BerNode.IsCompleteBER(result.Package,
                                                      0,
                                                      nInLen + wRet,
                                                      out long remainder);
                    if (bRet == true)
                    {
                        result.Length = nInLen + wRet;
                        break;
                    }
                }

                nInLen += wRet;
                if (nInLen >= result.Package.Length &&
                    bInitialLen == false)
                {
                    // 扩大缓冲区
                    if (nMaxLength != -1 && result.Package.Length >= nMaxLength)
                    {
                        throw new Exception("接收超过 " + nMaxLength + " bytes 也没有找到通讯包结束符");
                    }

                    byte[] temp = new byte[result.Package.Length + 4096];
                    Array.Copy(result.Package, 0, temp, 0, nInLen);
                    result.Package = temp;
                    result.Length  = result.Package.Length;
                }
            }

            // 最后规整缓冲区尺寸,如果必要的话
            if (result.Package.Length > result.Length)
            {
                byte[] temp = new byte[result.Length];
                Array.Copy(result.Package, 0, temp, 0, result.Length);
                result.Package = temp;
            }

            return(result);

#if NO
ERROR1:
            // this.CloseSocket();
            // baPackage = null;
            return(new RecvResult
            {
                Value = -1,
                ErrorInfo = strError,
                ErrorCode = result.ErrorCode
            });
#endif
        }
Exemple #10
0
        // (支持 Pipeline 的版本)
        // 接收通讯包
        // 本函数支持 Pipeline 方式。
        // parameters:
        //      cache   用来支持 Pipeline 方式,把多于一个通讯包的 bytes 部分,存储起来,下次先处理这部分内容
        //              如果为 null,表示不支持 Pipeline 方式
        //      nMaxLength  读入等待处理的 bytes 极限数字。超过了这个,还没有找到结束符,就会抛出异常。意在防范攻击。-1 表示不限制
        public static async Task <RecvResult> SimpleRecvTcpPackage(TcpClient client,
                                                                   List <byte> cache,
                                                                   Delegate_isComplete procIsComplete,
                                                                   delegate_touch touch_func = null,
                                                                   int nMaxLength            = 4096)
        {
            RecvResult result = new RecvResult();

            Debug.Assert(client != null, "client为空");

            List <byte> package = new List <byte>();

            int CHUNK_SIZE = 4096;

            // 优先从 cache 中复制数据过来进行处理
            if (cache != null && cache.Count > 0)
            {
                package = cache;
                cache.Clear();
            }

            while (true)
            {
                if (client == null)
                {
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorInfo = "通讯中断",
                        ErrorCode = "abort"
                    });
                }

                // byte[] temp = new byte[CHUNK_SIZE];
                byte[] temp = ArrayPool <byte> .Shared.Rent(CHUNK_SIZE);

                int current = 0;
                try
                {
                    current = await client.GetStream().ReadAsync(temp,
                                                                 0,
                                                                 CHUNK_SIZE).ConfigureAwait(false);

                    touch_func?.Invoke();

                    if (current > 0)
                    {
                        if (current == temp.Length)
                        {
                            package.AddRange(temp);
                        }
                        else
                        {
                            int i = 0;
                            foreach (byte b in temp)
                            {
                                if (i >= current)
                                {
                                    break;
                                }
                                package.Add(b);
                                i++;
                            }
                        }

                        // package.AddRange(GetValues<byte>(temp, current));
                    }
                }
                catch (SocketException ex)
                {
                    if (ex.ErrorCode == 10035)
                    {
                        System.Threading.Thread.Sleep(100);
                        continue;
                    }
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorInfo = "recv出错1: " + ex.Message,
                        // "ConnectionAborted"
                        ErrorCode = ((SocketException)ex).SocketErrorCode.ToString()
                    });
                }
                catch (Exception ex)
                {
                    result.Exception = ex;
                    if (ex is IOException && ex.InnerException is SocketException)
                    {
                        // "ConnectionAborted"
                        result.ErrorCode = ((SocketException)ex.InnerException).SocketErrorCode.ToString();
                    }
                    result.ErrorInfo = "recv出错2: " + ex.Message;
                    result.Value     = -1;
                    return(result);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(temp);
                }

                // 得到包的长度
                if (package.Count >= 1)
                {
                    var ret = procIsComplete(package.ToArray(),
                                             0,
                                             package.Count);
                    if (ret.Item1 > 0)
                    {
                        result.Length     = ret.Item1;
                        result.Terminator = ret.Item2;
                        // 将结束符后面多出来的部分复制到 cache 中,以便下一次调用处理
                        if (result.Length < package.Count)
                        {
                            if (cache == null)
                            {
                                throw new Exception("当前不支持 Pipeline 方式的请求。发现前端一次性发送了多于一个通讯包");
                            }
                            for (int i = result.Length; i < package.Count; i++)
                            {
                                cache.Add(package[i]);
                            }
                        }
                        break;
                    }
                }

                if (current == 0)
                {
                    return(new RecvResult
                    {
                        Value = -1,
                        ErrorCode = "Closed",
                        ErrorInfo = "Closed by remote peer"
                    });
                }

                if (nMaxLength != -1 && package.Count >= nMaxLength)
                {
                    throw new Exception("接收超过 " + nMaxLength + " bytes 也没有找到通讯包结束符");
                }
            }

            // 最后规整缓冲区尺寸,如果必要的话
            if (package.Count > result.Length)
            {
                package.RemoveRange(result.Length, package.Count - result.Length);
            }

            result.Package = package.ToArray();
            return(result);
        }
Exemple #11
0
        // 接收响应包
        internal async Task <RecvResult> SimpleRecvTcpPackage()
        {
            string     strError = "";
            RecvResult result   = new RecvResult();

            int  nInLen;
            int  wRet        = 0;
            bool bInitialLen = false;

            Debug.Assert(_client != null, "client为空");

            result.Package = new byte[4096];
            nInLen         = 0;
            result.Length  = 4096; //COMM_BUFF_LEN;

            while (nInLen < result.Length)
            {
                if (_client == null)
                {
                    strError = "通讯中断";
                    goto ERROR1;
                }

                try
                {
                    wRet = await _client.GetStream().ReadAsync(result.Package,
                                                               nInLen,
                                                               result.Package.Length - nInLen);
                }
                catch (SocketException ex)
                {
                    if (ex.ErrorCode == 10035)
                    {
                        System.Threading.Thread.Sleep(100);
                        continue;
                    }
                    strError = "recv出错: " + ex.Message;
                    goto ERROR1;
                }
                catch (Exception ex)
                {
                    strError = "recv出错: " + ex.Message;
                    goto ERROR1;
                }

                if (wRet == 0)
                {
                    strError = "Closed by remote peer";
                    goto ERROR1;
                }

                // 得到包的长度

                if ((wRet >= 1 || nInLen >= 1) &&
                    bInitialLen == false)
                {
                    bool bRet = BerNode.IsCompleteBER(result.Package,
                                                      0,
                                                      nInLen + wRet,
                                                      out long remainder);
                    if (bRet == true)
                    {
                        result.Length = nInLen + wRet;
                        break;
                    }
                }

                nInLen += wRet;
                if (nInLen >= result.Package.Length &&
                    bInitialLen == false)
                {
                    // 扩大缓冲区
                    byte[] temp = new byte[result.Package.Length + 4096];
                    Array.Copy(result.Package, 0, temp, 0, nInLen);
                    result.Package = temp;
                    result.Length  = result.Package.Length;
                }
            }

            // 最后规整缓冲区尺寸,如果必要的话
            if (result.Package.Length > result.Length)
            {
                byte[] temp = new byte[result.Length];
                Array.Copy(result.Package, 0, temp, 0, result.Length);
                result.Package = temp;
            }

            return(result);

ERROR1:
            // this.CloseSocket();
            // baPackage = null;
            return(new RecvResult {
                Value = -1, ErrorInfo = strError
            });
        }