tornado和异步IO的基本简单流程原理

tornado

#建立连接
from tornado.httpclient import AsyncHTTPClient
#发送请求
from tornado.httpclient import HTTPRequest
#事件循环
from tornado import ioloop
#接收的次数
REV_COUNTER = 0
#请求的次数
REQ_COUNTER = 0
def handle_response(reponse):
    """
    处理返回值内容(需要维护计数器,来停止IO循环),调用ioloop.IOLoop.current().stop
    :param reponse:
    :return:
    """
    if reponse.error:
        print("Error:",reponse.error)
    else:
        print(reponse.body)
    global REV_COUNTER
    REV_COUNTER+=1
    if REV_COUNTER == REQ_COUNTER:
        print(REQ_COUNTER)
        ioloop.IOLoop.current().stop()

def func():
    url_list = [
        'http://www.baidu.com',
        'http://www.bing.com',
    ]
    global REQ_COUNTER
    REQ_COUNTER = len(url_list)
    for url in url_list:
        print(url)
        #建立连接
        http_client = AsyncHTTPClient()
        #发送请求,handle_response是回调函数
        http_client.fetch(HTTPRequest(url),handle_response)
#添加函数,事件循环
ioloop.IOLoop.current().add_callback(func)
#获取响应结果,事件循环
ioloop.IOLoop.current().start()

异步IO的基本简单流程原理

#实现异步的基本流程
import socket
import select
req_list =[
    ["1.1.1.1",80],
    ["1.1.1.2",80],
]
conn_sock_list = []
sock_list = []
for i in req_list:
    client = socket.socket()
    #不等待
    client.setblocking(False)
    try:
        client.connect(i[0],i[1],)
    except Exception as e:
        pass
    sock_list.append(client)
    conn_sock_list.append(client)

while True:
    #IO的多路复用同步
    r,w,e = select.select(sock_list,conn_sock_list,[],1)
    #当其他人给咱们发送数据时候,我们可以接收r=[sk1]
    for sk in r:
        try:
            #接收8096数据,因为不知道接收到的数据是否都是8096字节的,所以得循环去接收
            while True:
                data = sk.recv(8096)
                if not data:
                    sock_list.remove(sk) #当数据为空时候,http是短链接,接收到返回的数据http断开,不会接收到任何数据,数据接收完不再接收把之前获取到的数据移除
        except Exception as e:
            pass
    #连接成功的socket,可以有下一步的进展
    for sk in w:
        sk.sendall("""GET /index HTTP/1.0\r\nHost:www.baidu.com\r\n\r\n""")
        #已经发送过的请求在socket删除
        conn_sock_list.remove(sk)
    if not sock_list:
        break

上面的异步IO有一个缺陷就是没有保存获取响应结果的数据,可以新建一个类来解决这个问题

#实现异步的基本流程
import socket
import select

class HttpContext(object):
    def __init__(self,sock):
        #client
        self.sock = sock
        #保存数据
        self.buffer = []

    def fileno(self):
        return self.sock.fileno


req_list =[
    ["1.1.1.1",80],
    ["1.1.1.2",80],
]
conn_sock_list = []
sock_list = []
for i in req_list:
    client = socket.socket()
    #不等待
    client.setblocking(False)
    try:
        client.connect(i[0],i[1],)
    except Exception as e:
        pass
    obj = HttpContext(client)
    sock_list.append(obj)
    conn_sock_list.append(obj)

while True:
    #IO的多路复用同步
    #r,w,e = select.select([socket.fileno,socket]->[HttpContext.fileno,HttpContext],conn_sock_list,[],1)
    r,w,e = select.select(sock_list.fileno,conn_sock_list,[],1)
    #当其他人给咱们发送数据时候,我们可以接收r=[sk1]
    for sk in r:
        try:
            #接收8096数据,因为不知道接收到的数据是否都是8096字节的,所以得循环去接收
            while True:
                data = sk.sock.recv(8096)
                #保存数据
                obj.buffer.append(data)
                if not data:
                    sock_list.remove(sk) #当数据为空时候,http是短链接,接收到返回的数据http断开,不会接收到任何数据,数据接收完不再接收把之前获取到的数据移除
        except Exception as e:
            pass
    #连接成功的socket,可以有下一步的进展
    for sk in w:
        sk.sock.sendall("""GET /index HTTP/1.0\r\nHost:www.baidu.com\r\n\r\n""")
        #已经发送过的请求在socket删除
        conn_sock_list.remove(sk)
    if not sock_list:
        break
posted @ 2019-10-12 00:34  智、心  阅读(434)  评论(0编辑  收藏  举报