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
Host:www.baidu.com
""")
#已经发送过的请求在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
Host:www.baidu.com
""")
#已经发送过的请求在socket删除
conn_sock_list.remove(sk)
if not sock_list:
break