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
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
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
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
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
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
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')
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
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
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
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
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
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
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, ))
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')
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
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
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
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
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
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)
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
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')
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