Ejemplo n.º 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
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
0
    def recv_http_head(cls, net_info, recv_para={}):
        """
        获取http报文头对象

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

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

        """
        if type(recv_para) != dict:
            recv_para = {}
        _result = CResult('00000')
        _result.data = None
        _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

        _recv_para = copy.deepcopy(recv_para)
        _recv_para['recv_len'] = 1

        with ExceptionTool.ignored_cresult(
            _result
        ):
            # 循环获取所有报文头内容
            _get_line_bytes = b''
            _last_is_ln = False  # 标记上一个字符是否回车换行
            while True:
                # 检查是否超时
                if (datetime.datetime.now() - _result.recv_time).total_seconds() * 1000 > _overtime:
                    # 已超时
                    _result.change_code(code='20403')
                    break

                _read_result = TcpIpService.recv_data(net_info, _recv_para)
                if not _read_result.is_success():
                    # 出现异常,直接返回失败
                    _read_result.data = None
                    _read_result.recv_time = _result.recv_time
                    return _read_result
                # 获取成功,判断是否回车换行
                _get_line_bytes = _get_line_bytes + _read_result.data
                if str(_read_result.data, "ascii") == "\n" and _last_is_ln:
                    # 已经连续遇到两次回车换行,说明报文头已收齐退出循环
                    break
                elif str(_read_result.data, "ascii") == "\n":
                    _last_is_ln = True
                    continue
                elif str(_read_result.data, "ascii") == "\r":
                    continue
                else:
                    # 其他字符,不是连续换行
                    _last_is_ln = False
                    continue
            # 取完报文头数据,转换为结构对象
            _result.data = MsgHTTP(_get_line_bytes, msg_id=None, obj_type=EnumMsgObjType.Bytes)
        return _result