IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 通过追源码解决:xmlrpc.client设定请求超时时间 -> 正文阅读

[网络协议]通过追源码解决:xmlrpc.client设定请求超时时间

一、背景:

我们都知道,RPC本质是一个代理模式,是在HTTP或HTTPS请求上面做的封装,那么别人封装好了,拿过来用就好了。这样带来了极大的遍历,但也就导致了另外的问题,有的时候就是不够灵活。在python项目X山中,有的地方用了xmlrpc.client , 但又缺少超时机制。

二、分析

直接上代码了

import xmlrpc.client

url = 'http://{}:{}'.format("127.0.0.1", 5678)
client = xmlrpc.client.ServerProxy(url)
client.f11()


点进去看看吧。在短短三行代码中,我们只能够发现,只有后两行,有机会传一个超时参数,再一看,倒数第一行,是自己定义的,那压力来到了xmlrpc.client.ServerProxy(url)

class ServerProxy:

    def __init__(self, uri, transport=None, encoding=None, verbose=False,
                 allow_none=False, use_datetime=False, use_builtin_types=False,
                 *, headers=(), context=None):
        # establish a "logical" server connection

        # get the url
        type, uri = urllib.parse._splittype(uri)
        if type not in ("http", "https"):
            raise OSError("unsupported XML-RPC protocol")
        self.__host, self.__handler = urllib.parse._splithost(uri)
        if not self.__handler:
            self.__handler = "/RPC2"

        if transport is None:
            if type == "https":
                handler = SafeTransport
                extra_kwargs = {"context": context}
            else:
                handler = Transport
                extra_kwargs = {}
            transport = handler(use_datetime=use_datetime,
                                use_builtin_types=use_builtin_types,
                                headers=headers,
                                **extra_kwargs)
        self.__transport = transport

        self.__encoding = encoding or 'utf-8'
        self.__verbose = verbose
        self.__allow_none = allow_none

这个构造函数,把眼睛看花也看不到timeout字样,于是搜了搜看到一种解决方案

xmlrpclib客户端请求超时-python黑洞网

这老哥说到人心坎,全局超时影响过于大了,但给的是python2的例子,而且包名和我的报名也有区别。

?

此事回头再看transport参数,

发现这个构造方法里面也确实只有这个参数能掀起一些波澜(这个结论存在马后炮成分),并且再构造方法里面出现了同名的类:Transport

因此,顺着继承重写方法的路往下走

Transport 类

代码就不全部粘贴了,搞一部分下来

##
# Standard transport class for XML-RPC over HTTP.
# <p>
# You can create custom transports by subclassing this method, and
# overriding selected methods.

class Transport:
 ? ?
def make_connection(self, host):


    #return an existing connection if possible.  This allows
    #HTTP/1.1 keep-alive.
    if self._connection and host == self._connection[0]:
        return self._connection[1]
    # create a HTTP connection object from a host descriptor
    chost, self._extra_headers, x509 = self.get_host_info(host)
    self._connection = host, http.client.HTTPConnection(chost)
    return self._connection[1]


class HTTPConnection:
    def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                 source_address=None, blocksize=8192): ?


关键点1:类前面的备注这里提示我们可以去继承这个类
关键点2:方法里面的HTTPConnection也存在timeout参数

?

继续顺着这个思路往下,咱们看看socket._GLOBAL_DEFAULT_TIMEOUT到底是个啥

这就是个OBJECT? ????????按照我的预期,应该是个数字.......?

给他打印出来看看

到这里,我觉得可能不用再追了,我的目标是解决问题,当你设置为_GLOBAL_DEFAULT_TIMEOUT, 那说明就是无限等待的。

三、实践

就按照这个思路,重写了Transport类

客户端思路如下

import http.client
import xmlrpc.client


class TimeoutTransport(xmlrpc.client.Transport):
    time_out = 60  # 单位:秒

    def make_connection(self, host):
        # return an existing connection if possible.  This allows
        # HTTP/1.1 keep-alive.
        if self._connection and host == self._connection[0]:
            return self._connection[1]
        # create a HTTP connection object from a host descriptor
        chost, self._extra_headers, x509 = self.get_host_info(host)
        self._connection = host, http.client.HTTPConnection(chost, timeout=self.time_out)
        return self._connection[1]

    def set_timeout(self, timeout):
        self.time_out = timeout


url = 'http://{}:{}'.format("127.0.0.1", 5678)
try:

    client = xmlrpc.client.ServerProxy(url, transport=TimeoutTransport())
    client.f11()
except Exception as e:
    print(e)
print("--------------------------")
try:
    client2 = xmlrpc.client.ServerProxy(url)
    client2.f11()
except Exception as e:
    print(e)


import sys
import time
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer


class ThreadXMLRPCServer(ThreadingMixIn, SimpleXMLRPCServer):
    name = "xml-server"


def f11():
    print("老子睡了")
    time.sleep(10000)
    print("老子醒了")
    return 11

server = ThreadXMLRPCServer(('0.0.0.0', 5678))
server.register_function(f11, "f11")
server.serve_forever()
 

四、测试

server日志

客户端日志:

若是不手动停止,怕是永远也等不到了呢~

?

?

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:48:22  更:2022-04-01 23:49:05 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:37:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码