• Socket+Select 实现单线程并发请求


    Socket+Select 实现单线程并发请求

    涉及知识点:

    • socket 编程;
    • http 协议中的请求和响应的基本格式;
    • select

    目的:

    • 理解单线程并发请求的基本实现方式;

    代码

    import socket
    from urllib.parse import urlparse
    from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
    
    
    class Connection:
        def __init__(self, url, loop):
            self.loop = loop
            self.selector = loop.selector
            self.loop.task_count += 1
    
            url = urlparse(url)
            host_and_port = url.netloc.split(":")
            self.host = host_and_port[0]
            if len(host_and_port) == 2:
                self.port = int(host_and_port[1])
            else:
                self.port = 80
            self.path = url.path
            if self.path == "":
                self.path = "/"
            self.data = b""
    
            # 建立socket连接
            self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            # 连接建立成功后调用self.connected
            self.selector.register(self.client.fileno(), EVENT_WRITE, self.connected)
            self.client.connect((self.host, self.port))
            self.client.setblocking(False)
    
        def connected(self, key):
            self.selector.unregister(key.fd)
            self.client.send(
                "GET {} HTTP/1.1
    Host:{}
    Connection:close
    
    ".format(self.path, self.host).encode("utf8"))
            # 有数据返回时调用self.readable
            self.selector.register(self.client.fileno(), EVENT_READ, self.readable)
    
        def readable(self, key):
            d = self.client.recv(1024)
            if d:
                self.data += d
            else:
                self.selector.unregister(key.fd)
                resp_body = self.data.decode("utf8").split("
    
    ")[1]
                self.loop.results.append(resp_body)
                self.client.close()
    
    
    class Loop:
        def __init__(self):
            # 任务数量
            self.task_count = 0
            self.stop = False
            self.selector = DefaultSelector()
            self.results = []
    
        def run(self):
            while self.task_count > len(self.results):
                ready = self.selector.select()
                for key, mask in ready:
                    key.data(key)
            return self.results
    
    
    if __name__ == "__main__":
        loop = Loop()
        base_url = "http://127.0.0.1:5001/items/{}"
        for i in range(1, 5):
            con = Connection(base_url.format(i), loop)
        res = loop.run()
        print(res)
        # 假设一个请求需要一秒, 如果使用传统同步请求的方式,那么5个请求就需要5秒中;
        # 使用代码中这种方式一共只需要1秒时间, 因为5个请求是同时发出去的.
    
  • 相关阅读:
    csharp customer style print
    C++各大有名库的介绍
    关联,依赖,泛化(又称继承分为扩展或包含),实现,聚合(共享),复合(组合)
    有关数据库设计经验简介
    Msxml2.XMLHTTP Microsoft.XMLHTTP new XMLHttpRequest
    用例图
    设计模式之抽象工厂模式
    银行软件业务开发分类杂谈多年前的旧文
    #ifndef、#def、#endif说明
    C#.NET向现有文件添加文本+创建一个新文本文件并写入一个字符串
  • 原文地址:https://www.cnblogs.com/aloe-n/p/13418362.html
Copyright © 2020-2023  润新知