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 _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 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 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