Exemple #1
0
    def recv_data(cls, net_info, recv_para={}):
        """
        从指定的网络连接中读取数据

        @param {object} net_info - 要读取数据的网络信息对象(例如socket对象)
        @param {dict} recv_para - 读取数据的参数(暂时无用)

        @returns {CResult} - 数据获取结果:
            result.code :'00000'-成功,'20403'-获取数据超时,其他为获取失败
            result.data :获取到的数据对象,为一个二元数组
                (proto_msg, msg) - MsgHTTP报文头,二进制报文数据
            result.recv_time : datetime 实际开始接受数据时间

        """
        # 子类必须定义该功能
        if type(recv_para) != dict:
            recv_para = {}
        _result = CResult('00000')
        _result.data = None
        _result.recv_time = datetime.datetime.now()
        with ExceptionTool.ignored_cresult(
            _result
        ):
            _head_result = cls.recv_http_head(net_info, recv_para)
            if not _head_result.is_success():
                return _head_result
            _proto_msg = _head_result.data

            _body_result = cls.recv_http_body(net_info, _proto_msg, recv_para)
            if not _body_result.is_success():
                return _body_result

            _result.data = (_proto_msg, _body_result.data)
        return _result
def func_case1_no_para_with_cresult():
    RunTool.get_global_logger().log(simple_log.INFO,
                                    'runing func_case1_no_para_with_cresult')
    time.sleep(0.001)
    _ret = CResult()
    _ret.self_para = [3, 'str']
    return _ret
Exemple #3
0
    def test(self):
        """
        检测连接是否有效

        @returns {CResult} - 响应对象,判断成功的方法:
            ret.status == msg_pb2.HealthResponse.SERVING
            总共有以下几种状态
            health_pb2.HealthResponse.UNKNOWN
            health_pb2.HealthResponse.SERVICE_UNKNOWN
            health_pb2.HealthResponse.NOT_SERVING
            health_pb2.HealthResponse.SERVING
        """
        _check_result = CResult()
        if self._channel is None:
            # 没有连接
            _check_result.status = msg_pb2.HealthResponse.UNKNOWN
        elif self._test_use_health_check:
            # 使用标准健康检查
            self._health_stub = SimpleGRpcTools.generate_health_check_stub(
                self._channel)
            _check_result = SimpleGRpcTools.health_check_by_stub(
                self._health_stub, self._servicer_name, timeout=self._timeout)
        else:
            # 使用自定义的健康检查
            _check_result = SimpleGRpcTools.simple_grpc_health_check_by_stub(
                self._stub, timeout=self._timeout)
        # 返回结果
        return _check_result
    def _stop_server_predeal_self(self, tid, server_info):
        """
        自定义服务停止前处理函数,实现类可重载该函数加入自己的处理逻辑(例如结束子线程)

        @param {int} tid - 线程id
        @param {object} server_info - _start_server_self函数生成的server_info信息

        @returns {CResult} - 处理结果:
            result.code :'00000'-成功,其他值为失败
            result.is_finished :处理是否已完成,True - 已处理完成,False - 未完成,需循环再处理

        """
        _result = CResult(code='00000')  # 成功
        _result.is_finished = True
        with ExceptionTool.ignored_cresult(
                _result,
                logger=self._logger,
                self_log_msg='[%s-STOPING][NAME:%s]%s: ' %
            (self._server_log_prefix, self._server_name,
             _('stop service predeal error')),
                force_log_level=logging.ERROR):
            # 可在该部分实现自定义逻辑
            pass
        # 返回处理结果
        return _result
Exemple #5
0
    def recv_http_body(cls, net_info, proto_msg, recv_para={}):
        """
        获取http报文体信息

        @param {object} net_info -  要读取数据的网络信息对象
        @param {MsgHTTP} proto_msg - http报文头
        @param {dict} recv_para - 获取参数,暂未使用

        @returns {CResult} - 数据获取结果:
            result.code :'00000'-成功,'20403'-获取数据超时,其他为获取失败
            result.msg :获取到的数据对象,类型为bytes
            result.recv_time : datetime 实际开始接受数据时间

        """
        if type(recv_para) != dict:
            recv_para = {}
        _recv_para = copy.deepcopy(recv_para)
        _result = CResult('00000')
        _result.data = None
        _result.recv_time = datetime.datetime.now()
        with ExceptionTool.ignored_cresult(
            _result
        ):
            _get_value = proto_msg.get_value(search_path='Content-Length')
            if _get_value is not None:
                _len = int(_get_value)
                _recv_para['recv_len'] = _len
                _recv_result = TcpIpService.recv_data(net_info, _recv_para)
                _result = _recv_result
        return _result
Exemple #6
0
def on_exit(message='', prompt_obj=None, **kwargs):
    """Ctrl + D : exit,关闭命令行"""
    if prompt_obj is not None:
        prompt_obj.prompt_print('on_exit: %s' % message)
    _result = CResult(code='10100')
    _result.print_str = 'on_exit done!'
    return _result
    def _server_run_self(self, tid, server_info):
        """
        自定义服务处理函数,实现类可重载该函数加入自己的处理逻辑(例如进行实际业务处理)
            注意:该函数每次只处理一次就应该返回,且应该实现异常处理

        @param {int} tid - 线程id
        @param {object} server_info - _start_server_self函数生成的server_info信息

        @returns {CResult} - 处理结果:
            result.code :'00000'-成功,其他值为失败
            result.is_finished :处理是否已完成,True - 已处理完成,False - 未完成,需循环再处理

        """
        _result = CResult(code='00000')  # 成功
        _result.is_finished = False
        with ExceptionTool.ignored_cresult(
                _result,
                logger=self._logger,
                self_log_msg='[%s][NAME:%s]%s: ' %
            (self._server_log_prefix, self._server_name,
             _('service run error')),
                force_log_level=logging.ERROR):
            # 可在该部分实现自定义逻辑
            pass
        # 返回处理结果
        return _result
Exemple #8
0
    def _start_server_self(self, tid):
        """
        自定义服务启动函数,实现类可重载该函数加入自己的处理逻辑
        重载该函数,实现网络监听服务的启动,但不接收连接

        @param {int} tid - 线程id

        @returns {CResult} - 启动结果:
            result.code :'00000'-成功,其他值为失败
            result.server_info :启动成功后的服务对象,用于传递到后续的服务处理函数

        """
        _result = CResult(code='00000')  # 成功
        _result.server_info = NullObj()
        with ExceptionTool.ignored_cresult(_result):
            # 可在该部分实现自定义逻辑
            self._logger.log(
                self._log_level,
                '[%s-STARTING][NAME:%s]%s:\n%s' % (
                    self._server_log_prefix,
                    self._server_name,
                    _('net start parameter'),
                    StringTool.format_obj_property_str(self._server_opts, is_deal_subobj=True)
                )
            )

            # 启动服务,但不接受连接
            _result = self._start_server_without_accept(self._server_opts)
            _result.server_info = _result.net_info

        # 返回处理结果
        return _result
Exemple #9
0
def on_abort(message='', prompt_obj=None, **kwargs):
    """Ctrl + C : abort,取消本次输入"""
    if prompt_obj is not None:
        prompt_obj.prompt_print('on_abort: %s' % message)
    _result = CResult()
    _result.print_str = 'on_abort done!'
    return _result
Exemple #10
0
    def _i18n_result_obj(self, result, prompt_obj=None, is_i18n=True):
        """
        公共的处理返回结果国际化处理及打印函数

        @param {CResult} - 处理结果,如果不是CResult则返回成功的结果
        """
        _type = type(result)
        if _type == CResult:
            # 错误对象
            if hasattr(result, 'print_str') and result.print_str != '':
                prompt_obj.prompt_print(
                    _(result.print_str) if is_i18n else result.print_str)
                result.print_str = ''

            if is_i18n:
                result.msg = _(result.i18n_msg_id, result.i18n_msg_paras)
            return result
        elif _type == str:
            # 字符串
            prompt_obj.prompt_print(_(result) if is_i18n else result)
            return CResult(code='00000')
        elif isinstance(result, Iterator):
            # 是迭代器
            _last_result = CResult(code='00000')
            for _result in result:
                # 回调自己进行处理
                _last_result = self._i18n_result_obj(_result, prompt_obj)

            return _last_result
        else:
            # 当作字符串处理
            prompt_obj.prompt_print(_(str(result)) if is_i18n else str(result))
            return CResult(code='00000')
Exemple #11
0
    def send_data(cls, net_info, data, send_para={}):
        """
        向指定的网络连接发送数据

        @param {object} net_info - 要写入数据的网络信息对象(例如socket对象)
        @param {tuple} data - 要写入的数据对象,(proto_msg, msg)
            proto_msg : MsgHTTP报文头
            msg : 二进制数据
        @param {dict} send_para - 写入数据的参数

        @returns {CResult} - 发送结果:
            result.code :'00000'-成功,'20404'-写入数据超时,其他为写入失败
            result.send_time : datetime 实际发送完成时间

        """
        # 子类必须定义该功能
        if type(send_para) != dict:
            send_para = {}
        _result = CResult('00000')
        _result.send_time = None
        with ExceptionTool.ignored_cresult(
            _result
        ):
            # 先要更新报文头的长度
            _len = 0
            if data[1] is not None:
                _len = len(data[1])
            data[0].set_value('Content-Length', str(_len))
            _send_result = TcpIpService.send_data(net_info, data[0].to_bytes(), send_para)
            if not _send_result.is_success():
                return _send_result
            if _len > 0:
                _send_result = TcpIpService.send_data(net_info, data[1], send_para)
                _result = _send_result
        return _result
    def start_server(self, is_wait=False):
        """
        启动服务
        注意服务必须处于停止状态才能启动

        @param {bool} is_wait=False - 是否等待服务启动完成后再退出

        @returns {CResult} - 启动结果,result.code:'00000'-成功,'21401'-服务不属于停止状态,不能启动,其他-异常

        """
        _result = CResult(code='00000')  # 成功
        with ExceptionTool.ignored_cresult(
                _result,
                logger=self._logger,
                self_log_msg='[%s-STARTING][NAME:%s]%s: ' %
            (self._server_log_prefix, self._server_name,
             _('start service error')),
                force_log_level=logging.ERROR):
            # 先获取锁,拿到最准确的服务状态
            self.__server_run_status_lock.acquire()
            try:
                if self.__server_run_status != EnumServerRunStatus.Stop:
                    # 不属于停止状态,不能启动
                    _temp_result = CResult(code='21401')  # 服务启动失败-服务已启动
                    self._logger.log(
                        self._log_level, '[%s-STARTING][NAME:%s]%s' %
                        (self._server_log_prefix, self._server_name,
                         _temp_result.msg))
                    return _temp_result

                # 执行启动服务的动作,通过线程方式启动,避免调用方等待
                self.__server_begin_time = datetime.datetime.now()
                self._logger.log(
                    self._log_level, '[%s-STARTING][NAME:%s]%s' %
                    (self._server_log_prefix, self._server_name,
                     _('service starting')))
                self._server_status_change(EnumServerRunStatus.WaitStart,
                                           _result)
                _server_thread = threading.Thread(
                    target=self.__start_server_thread_fun,
                    args=(1, ),
                    name='Thread-Server-Main')
                _server_thread.setDaemon(True)
                _server_thread.start()
            finally:
                # 释放锁
                self.__server_run_status_lock.release()

        # 返回结果,循环等待
        while is_wait and self.__server_run_status == EnumServerRunStatus.WaitStart:
            RunTool.sleep(0.01)

        # 如果是等待模式,检查一次结果,如果没有正常运行返回最后一次启动结果
        if is_wait:
            if self.__server_run_status != EnumServerRunStatus.Running:
                _result = self.__last_start_result

        return _result
Exemple #13
0
    def _accept_one(self, server_opts, net_info):
        """
        监听接受一个请求并返回
        提供监听并获取到请求连接返回的方法;注意该该函数必须捕获并处理异常

        @param {objcet} server_opts - 网络服务启动参数
        @param {objcet} net_info - 网络连接信息对象,_start_server_without_accept中获取到的结果

        @returns {CResult} - 获取网络连接结果:
            result.code :'00000'-成功,'20407'-获取客户端连接请求超时
            result.net_info :客户端连接信息对象,该对象将传给后续单个连接处理的线程

        """
        # 子类必须定义该功能
        _result = CResult('00000')
        _result.net_info = None
        with ExceptionTool.ignored_cresult(
            _result,
            logger=self._logger,
            expect=(BlockingIOError),
            expect_no_log=True,  # 超时不记录日志
            error_map={BlockingIOError: ('20407', None)},
            self_log_msg='[LIS][NAME:%s]%s error: ' % (
                self._server_name, _('accept client connect')),
            force_log_level=None
        ):
            # _sys_str = platform.system()
            _csocket, _addr = net_info.csocket.accept()  # 接收客户端连接,返回客户端和地址
            _csocket.setblocking(False)   # 将socket设置为非阻塞. 在创建socket对象后就进行该操作.
            _result.net_info = NullObj()
            _result.net_info.csocket = _csocket
            _result.net_info.raddr = _addr
            _result.net_info.laddr = _csocket.getsockname()
            _result.net_info.send_timeout = server_opts.send_timeout
            _result.net_info.recv_timeout = server_opts.recv_timeout

            # 采用非阻塞模式处理数据,超时自行实现
            """
            if (_sys_str == 'Windows'):
                _csocket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO, server_opts.recv_timeout)
                _csocket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO, server_opts.send_timeout)
            else:
                # linux 设置超时时间不同,需重新测试
                _csocket.settimeout(server_opts.recv_timeout / 1000)
            """
            self._logger.log(
                self._log_level,
                '[LIS][NAME:%s]%s: %s - %s' % (
                    self._server_name, _('accept one client connection'), str(_addr), str(_csocket)
                )
            )
        if not _result.is_success():
            # 出现异常,睡眠一段时间
            RunTool.sleep(0.01)
        return _result
Exemple #14
0
def dir_cmd_dealfun(message='',
                    cmd='',
                    cmd_para='',
                    prompt_obj=None,
                    **kwargs):
    """dir命令的处理函数"""
    if prompt_obj is not None:
        prompt_obj.prompt_print('dir: message[%s], cmd[%s], cmd_para[%s]' %
                                (message, cmd, cmd_para))
    _result = CResult()
    _result.print_str = 'dir_cmd_dealfun done!'
    return _result
Exemple #15
0
    def _server_run_self(self, tid, server_info):
        """
        自定义服务处理函数,实现类可重载该函数加入自己的处理逻辑(例如进行实际业务处理)
            注意:该函数每次只处理一次就应该返回,且应该实现异常处理

        @param {int} tid - 线程id
        @param {object} server_info - _start_server_self函数生成的server_info信息

        @returns {CResult} - 处理结果:
            result.code :'00000'-成功,其他值为失败
            result.is_finished :处理是否已完成,True - 已处理完成,False - 未完成,需循环再处理

        """
        _result = CResult(code='00000')  # 成功
        _result.is_finished = False
        with ExceptionTool.ignored_cresult(
            _result,
            logger=self._logger,
            self_log_msg='[%s][NAME:%s]%s: ' % (
                self._server_log_prefix, self._server_name, _('service run error')),
            force_log_level=logging.ERROR
        ):
            # 可在该部分实现自定义逻辑
            # 监听下一个连接请求
            _accept_result = self._accept_one(self._server_opts, server_info)
            if _accept_result.is_success():
                # 获取到一个连接,创建线程
                self.__server_connect_thread_id = self.__server_connect_thread_id + 1
                _thread_id = self.__server_connect_thread_id
                _new_thread = threading.Thread(
                    target=self.__server_connect_thread_fun,
                    args=(_thread_id, self._server_opts, _accept_result.net_info),
                    name='Thread-ConnectDeal' + str(_thread_id)
                )
                self.__server_connect_thread_add(_thread_id, _new_thread)
                _new_thread.setDaemon(True)
                _new_thread.start()
            elif _accept_result.code != '20407':
                # 不是超时的其他获取错误,打印信息
                self._logger.log(
                    logging.ERROR,
                    "[%s][NAME:%s][EX:%s]%s: %s\n%s" % (
                        self._server_log_prefix,
                        self._server_name, str(type(_accept_result.error)),
                        _('accept net connection error'), _accept_result.msg,
                        _accept_result.trace_str
                    )
                )
            else:
                # 监听超时
                pass
        # 返回处理结果
        return _result
Exemple #16
0
def default_cmd_dealfun(message='',
                        cmd='',
                        cmd_para='',
                        prompt_obj=None,
                        **kwargs):
    """默认命令处理函数"""
    if prompt_obj is not None:
        prompt_obj.prompt_print(
            'cmd not define: message[%s], cmd[%s], cmd_para[%s]' %
            (message, cmd, cmd_para))
    _result = CResult()
    _result.print_str = 'default_cmd_dealfun done!'
    return _result
Exemple #17
0
    def _start_server_without_accept(self, server_opts):
        """
        启动服务但不接受请求服务,该方法只做到启动端口层面,轮询监听不在该方法中实现:

        @param {object} server_opts - 服务参数

        @returns {CResult} - 启动结果:
            result.code :'00000'-成功,其他值为失败
            result.net_info :启动后的服务端网络连接信息对象,该对象将传给后续的监听线程(_AcceptOne),定义为:
                result.net_info.csocket - socket对象
                result.net_info.laddr 本地地址,地址对象,("IP地址",打开端口)
                result.net_info.raddr 远端地址,地址对象,("IP地址",打开端口)
                result.net_info.send_timeout 发送超时时间,单位为毫秒
                result.net_info.recv_timeout 收取超时时间,单位为毫秒

        """
        # 子类必须定义该功能
        _result = CResult('00000')
        _result.net_info = None
        with ExceptionTool.ignored_cresult(
            _result,
            logger=self._logger,
            self_log_msg='[LIS-STARTING][NAME:%s]%s - %s error: ' % (
                self._server_name, _('net service starting'), _('listen without accept')),
            force_log_level=logging.ERROR
        ):
            # _sys_str = platform.system()
            _server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            _server_socket.setblocking(False)   # 将socket设置为非阻塞. 在创建socket对象后就进行该操作.
            _server_socket.bind((server_opts.ip, server_opts.port))
            _server_socket.listen(server_opts.max_connect)
            # 改为用非阻塞模式支持,因此超时自行实现
            """
            if (_sys_str == 'Windows'):
                _server_socket.setsockopt(
                    socket.SOL_SOCKET, socket.SO_RCVTIMEO, server_opts.recv_timeout)
                _server_socket.setsockopt(
                    socket.SOL_SOCKET, socket.SO_SNDTIMEO, server_opts.send_timeout)
            else:
                # linux 设置超时时间不同,需重新测试
                _server_socket.settimeout(server_opts.recv_timeout/1000)
            """
            _result.net_info = NullObj()
            _result.net_info.laddr = _server_socket.getsockname()
            # _result.net_info.raddr = _server_socket.getpeername()
            _result.net_info.raddr = ('', 0)
            _result.net_info.csocket = _server_socket
            _result.net_info.send_timeout = server_opts.send_timeout
            _result.net_info.recv_timeout = server_opts.recv_timeout

        return _result
Exemple #18
0
    def _cmd_dealfun(self, message='', cmd='', cmd_para='', prompt_obj=None, **kwargs):
        """
        通用处理函数,通过cmd区别调用实际的处理函数

        @param {string} message='' - prompt提示信息
        @param {string} cmd - 执行的命令key值
        @param {string} cmd_para - 传入的命令参数(命令后的字符串,去掉第一个空格)
        @param {PromptPlus} prompt_obj=None - 传入调用函数的PromptPlus对象,可以通过该对象的一些方法控制输出显示
        @param {kwargs} - 传入的主进程的初始化kwargs对象

        @returns {CResult} - 命令执行结果,可通过返回错误码10101通知框架退出命令行, 同时也可以通过CResult对象的
            print_str属性要求框架进行打印处理
        """
        # 获取真实执行的函数
        self._prompt_obj = prompt_obj  # 传递到对象内部处理
        _real_dealfun = None  # 真实调用的函数
        if 'ignore_case' in kwargs.keys() and kwargs['ignore_case']:
            # 区分大小写
            if cmd in self._CMD_DEALFUN_DICT.keys():
                _real_dealfun = self._CMD_DEALFUN_DICT[cmd]
        else:
            # 不区分大小写
            if cmd.lower() in self._CMD_DEALFUN_DICT.keys():
                _real_dealfun = self._CMD_DEALFUN_DICT[cmd.lower()]

        # 执行函数
        if _real_dealfun is not None:
            return _real_dealfun(message=message, cmd=cmd, cmd_para=cmd_para, prompt_obj=prompt_obj, **kwargs)
        else:
            prompt_obj.prompt_print(_("'$1' is not support command!", cmd))
            return CResult(code='11404', i18n_msg_paras=(cmd, ))
Exemple #19
0
    def _cd_cmd_dealfun(self,
                        message='',
                        cmd='',
                        cmd_para='',
                        prompt_obj=None,
                        **kwargs):
        """
        切换当前工作目录命令

        @param {string} message='' - prompt提示信息
        @param {string} cmd - 执行的命令key值
        @param {string} cmd_para - 传入的命令参数(命令后的字符串,去掉第一个空格)
        @param {PromptPlus} prompt_obj=None - 传入调用函数的PromptPlus对象,可以通过该对象的一些方法控制输出显示
        @param {kwargs} - 传入的主进程的初始化kwargs对象

        @returns {CResult} - 命令执行结果,可通过返回错误码10101通知框架退出命令行, 同时也可以通过CResult对象的
            print_str属性要求框架进行打印处理
        """
        _word_path = cmd_para.strip()
        os.chdir(_word_path)  # 改变工作目录,如果没有异常则认为成功
        self._console_global_para['work_path'] = os.getcwd()
        prompt_obj.prompt_print(
            _('Current work path is: $1',
              self._console_global_para['work_path']))
        return CResult(code='00000')
Exemple #20
0
    def connect(self, **kwargs):
        """
        连接远端服务器
        (对于长连接或有需要实现先连接再处理的场景使用,其他场景无需重构该函数)

        @param {**kwargs} kwargs - 连接参数(具体由实现类定义)

        @returns {HiveNetLib.generic.CResult} - 处理结果(符合HiveNet 错误码规范)
            当处理结果为成功时,通过CResult返回结果对象:
            CResult.proto_obj {object}  - 协议通讯对象
            CResult.net_info {object}  - 网络连接信息

        """
        _ret = CResult(code='00000')
        _ret.proto_obj = self.__proto_obj
        _ret.net_info = self.__net_info
        return _ret
Exemple #21
0
    def _stop_server_predeal_self(self, tid, server_info):
        """
        自定义服务停止前处理函数,实现类可重载该函数加入自己的处理逻辑(例如结束子线程)
        重载该函数,检查连接子线程是否均已结束,否则返回未完成,继续等待下一次检查

        @param {int} tid - 线程id
        @param {object} server_info - _start_server_self函数生成的server_info信息

        @returns {CResult} - 处理结果:
            result.code :'00000'-成功,其他值为失败
            result.is_finished :处理是否已完成,True - 已处理完成,False - 未完成,需循环再处理

        """
        _result = CResult(code='00000')  # 成功
        _result.is_finished = True
        if len(self.__server_connect_thread_list.keys()) > 0:
            _result.is_finished = False
        return _result
Exemple #22
0
def help_cmd_dealfun(message='',
                     cmd='',
                     cmd_para='',
                     prompt_obj=None,
                     **kwargs):
    """帮助命令,输出提示信息"""
    if prompt_obj is not None:
        prompt_obj.prompt_print(cmd_para_descript)
    return CResult()
    def _start_server_self(self, tid):
        """
        自定义服务启动函数,实现类可重载该函数加入自己的处理逻辑

        @param {int} tid - 线程id

        @returns {CResult} - 启动结果:
            result.code :'00000'-成功,其他值为失败
            result.server_info :启动成功后的服务对象,用于传递到后续的服务处理函数

        """
        _result = CResult(code='00000')  # 成功
        _result.server_info = NullObj()
        with ExceptionTool.ignored_cresult(_result):
            # 可在该部分实现自定义逻辑
            pass
        # 返回处理结果
        return _result
Exemple #24
0
    def recv_data(cls, net_info, recv_para={}):
        """
        从指定的网络连接中读取数据

        @param {object} net_info - 要读取数据的网络信息对象(例如socket对象)
        @param {dict} recv_para - 读取数据的参数, 包括:
            recv_len {int} - 要获取的数据长度, 必要参数
            overtime {int} - 获取超时时间,单位为毫秒,非必要参数

        @returns {CResult} - 数据获取结果:
            result.code :'00000'-成功,'20403'-获取数据超时,其他为获取失败
            result.data :获取到的数据对象(具体类型和定义,由实现类自定义)
            result.recv_time : datetime 实际开始接受数据时间
            result.overtime : int 超时时间(毫秒),当返回结果为超时,可获取超时时间信息

        """
        # 子类必须定义该功能
        if type(recv_para) != dict:
            recv_para = {}
        _result = CResult('00000')
        _result.data = b''
        _result.recv_time = datetime.datetime.now()
        _overtime = 10000
        if 'overtime' in recv_para.keys():
            # 外部有传入,优先使用该超时时间
            _overtime = recv_para['overtime']
        elif hasattr(net_info, 'recv_timeout'):
            # 如果net_info有超时的设置
            _overtime = net_info.recv_timeout
        _result.overtime = _overtime

        with ExceptionTool.ignored_cresult(
            _result
        ):
            _rest_bytes = recv_para['recv_len']
            while _rest_bytes > 0:
                # 检查是否超时
                if (datetime.datetime.now() - _result.recv_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20403')
                    break

                _buffer = b''
                with ExceptionTool.ignored(expect=(BlockingIOError)):
                    # 获取数据
                    _buffer = net_info.csocket.recv(_rest_bytes)
                    if len(_buffer) > 0:
                        _result.data = _result.data + _buffer
                        _rest_bytes = _rest_bytes - len(_buffer)
                    else:
                        # 休眠一下
                        RunTool.sleep(0.001)
        return _result
Exemple #25
0
def common_cmd_dealfun(message='',
                       cmd='',
                       cmd_para='',
                       prompt_obj=None,
                       **kwargs):
    """通用命令处理函数,持续10秒每秒输出一个wait的信息"""
    if prompt_obj is not None:
        prompt_obj.prompt_print('common: message[%s], cmd[%s], cmd_para[%s]' %
                                (message, cmd, cmd_para))

    if cmd == 'wait':
        _i = 0
        while _i < 10:
            _logger.info('wait ' + str(_i))
            _i = _i + 1
            time.sleep(1)

    _result = CResult()
    _result.print_str = 'common_cmd_dealfun done!'
    return _result
Exemple #26
0
    def connect_server(cls, connect_para):
        """
        客户端通过该函数连接服务器端

        @param {object} connect_para - 需要连接服务器的参数,与server_opts一致

        @returns {CResult} - 连接结果:
            result.code :'00000'-成功,其他值为失败
            result.net_info : 连接后的网络信息对象

        """
        # 子类必须定义该功能
        _result = CResult('00000')
        _result.net_info = None
        with ExceptionTool.ignored_cresult(
            _result,
            logger=None
        ):
            # _sys_str = platform.system()
            _tcp_cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 分配 TCP 客户端套接字
            _tcp_cli_sock.connect((connect_para.ip, connect_para.port))  # 主动连接
            _tcp_cli_sock.setblocking(False)   # 将socket设置为非阻塞. 在创建socket对象后就进行该操作.

            # 转换为非阻塞模式,自行控制超时
            """
            if (_sys_str == 'Windows'):
                _tcp_cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
                                         connect_para.recv_timeout)
                _tcp_cli_sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDTIMEO,
                                         connect_para.send_timeout)
            else:
                # linux 设置超时时间不同,需重新测试
                _tcp_cli_sock.settimeout(connect_para.recv_timeout / 1000)
            """
            _result.net_info = NullObj()
            _result.net_info.csocket = _tcp_cli_sock
            _result.net_info.laddr = _tcp_cli_sock.getsockname()
            _result.net_info.raddr = _tcp_cli_sock.getpeername()
            _result.net_info.send_timeout = connect_para.send_timeout
            _result.net_info.recv_timeout = connect_para.recv_timeout
        return _result
    def test_methon(self):
        """
        测试静态方法
        """
        _logger = Logger()
        _result = CResult('00000')
        _result.net_info = None
        with ExceptionTool.ignored_cresult(_result,
                                           logger=_logger,
                                           expect=(),
                                           error_map={
                                               ImportError: ('20401', None),
                                               BlockingIOError: ('20407', None)
                                           },
                                           self_log_msg='test:',
                                           force_log_level=None):
            _result.test = 'test'

        self.assertTrue(_result.code == '00000' and _result.test == 'test',
                        'ok result error')

        _result = CResult('00000')
        with ExceptionTool.ignored_cresult(_result,
                                           logger=_logger,
                                           expect=(),
                                           error_map={
                                               ImportError: ('20401', None),
                                               BlockingIOError: ('20407', None)
                                           },
                                           self_log_msg='test:',
                                           force_log_level=None):
            raise ImportError

        self.assertTrue(_result.code == '20401',
                        '20401 result error, code:' + _result.code)

        _result = CResult('00000')
        with ExceptionTool.ignored_cresult(_result,
                                           logger=_logger,
                                           expect=(),
                                           error_map={
                                               ImportError: ('20401', None),
                                               BlockingIOError: ('20407', None)
                                           },
                                           self_log_msg='test:',
                                           force_log_level=None):
            raise BlockingIOError

        self.assertTrue(_result.code == '20407',
                        '20407 result error, code:' + _result.code)
Exemple #28
0
    def reconnect(self):
        """
        重新连接

        @returns {CResult} - 响应对象,判断成功的方法:
            ret.status == msg_pb2.HealthResponse.SERVING
            总共有以下几种状态
            health_pb2.HealthResponse.UNKNOWN
            health_pb2.HealthResponse.SERVICE_UNKNOWN
            health_pb2.HealthResponse.NOT_SERVING
            health_pb2.HealthResponse.SERVING
        """
        # 先关闭连接
        self.close()

        # 进行连接
        self._channel = SimpleGRpcTools.generate_channel(self._connect_para)
        self._stub = SimpleGRpcTools.generate_call_stub(self._channel)

        # 检查连接有效性
        if self._test_on_connect:
            _check_result = self.test()
            if not _check_result.is_success(
            ) or _check_result.status != msg_pb2.HealthResponse.SERVING:
                # 连接失败,打印日志后抛出异常
                if self._logger is not None:
                    self._logger.log(
                        self._log_level, '[EX:%s]%s%s, service status:%s\n%s' %
                        (_check_result.error,
                         'SimpleGRpcConnection reconnect error: ',
                         _check_result.msg, _check_result.status,
                         _check_result.trace_str))
            return _check_result
        else:
            # 不检查的情况,直接返回成功,连接状态为SERVING
            _check_result = CResult('00000')
            _check_result.status = msg_pb2.HealthResponse.SERVING
            return _check_result
Exemple #29
0
    def _cmd_dealfun(self,
                     message='',
                     cmd='',
                     cmd_para='',
                     prompt_obj=None,
                     **kwargs):
        """
        Ctrl + D : exit,关闭命令行

        @param {string} message='' - prompt提示信息
        @param {string} cmd - 执行的命令key值
        @param {string} cmd_para - 传入的命令参数(命令后的字符串,去掉第一个空格)
        @param {PromptPlus} prompt_obj=None - 传入调用函数的PromptPlus对象,可以通过该对象的一些方法控制输出显示
        @param {kwargs} - 传入的主进程的初始化kwargs对象

        @returns {CResult} - 命令执行结果,可通过返回错误码10101通知框架退出命令行, 同时也可以通过CResult对象的
            print_str属性要求框架进行打印处理
        """
        if self._console_global_para['exit_with_prompt'] == 'n':
            # 不由用户选择直接退出
            prompt_obj.prompt_print(
                _("Exit $1 Console", self._console_global_para['name']))
            return CResult(code='10101')

        _tip = _('You will shutdown $1 console, continue?(y/N)',
                 self._console_global_para['name'])
        _back = input(_tip)
        if _back.upper() == 'Y':
            # 退出
            prompt_obj.prompt_print(
                _("Exit $1 Console", self._console_global_para['name']))
            return CResult(code='10101')
        else:
            # 取消退出
            prompt_obj.prompt_print(_("Cancel Exit"))
            return CResult(code='00000')
Exemple #30
0
    def send_data(cls, net_info, data, send_para={}):
        """
        向指定的网络连接发送数据

        @param {object} net_info - 要写入数据的网络信息对象(例如socket对象)
        @param {object} data - 要写入的数据对象(具体类型和定义,由实现类自定义)
        @param {dict} send_para - 写入数据的参数:
            overtime {int} - 发送超时时间,单位为毫秒, 非必须参数
        @returns {CResult} - 发送结果:
            result.code :'00000'-成功,'20404'-写入数据超时,其他为写入失败
            result.send_time : datetime 实际发送完成时间
            result.overtime : int 超时时间(毫秒),当返回结果为超时,可获取超时时间信息

        """
        # 子类必须定义该功能
        if type(send_para) != dict:
            send_para = {}
        _result = CResult('00000')
        _result.send_time = None
        _overtime = 10000
        if 'overtime' in send_para.keys():
            _overtime = send_para['overtime']
        elif hasattr(net_info, 'send_timeout'):
            # 如果net_info有超时的设置
            _overtime = net_info.send_timeout
        _result.overtime = _overtime

        _begin_time = datetime.datetime.now()

        with ExceptionTool.ignored_cresult(
            _result
        ):
            _rest_bytes = len(data)
            _total_bytes = _rest_bytes
            while _rest_bytes > 0:
                # 检查是否超时
                if (datetime.datetime.now() - _begin_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20404')
                    break
                with ExceptionTool.ignored(expect=(BlockingIOError)):
                    # 发送数据
                    _len = net_info.csocket.send(data[_total_bytes - _rest_bytes:])
                    if _len > 0:
                        _rest_bytes = _rest_bytes - _len

            _result.send_time = datetime.datetime.now()
        return _result