import asyncio
@asyncio.coroutine
def wget(host):
print('wget %s... ' % host)
#asyncio.open_connection接受host参数和port参数以及一些可选的
#关键字参数.返回一个reader和一个writer,
#redaer is a StreamReader instance;
#the writer is a StreamWriter instance. 这两句话什么意思?
#writer.write就和socket.send差不多…
connect = asyncio.open_connection(host, 80)
#print(connect)
reader, writer = yield from connect
#print('reader:', reader)
#print('writer:', writer)
header = 'GET / HTTP/1.0\r\nHost: %s\r\n\r\n' % host
writer.write(header.encode('utf-8'))
#[1]:对于writer.drain()的用法,它会阻塞如果writer的buffer已经满了…
#当然在我们这个例子里面buffer是充足的,因为我们只发送了几个GET请求。
#内存总线在同一时刻只能服务写操作或者读操作中的一种,这是因为总线只能以一个方向驱动。
#之前的内存控制器将写缓冲在一个写队列中来允许读请求充分利用内存总吸纳,当写队列满时,
#或者达到某一个水位,内存调度其就或切换到write drain模式,这时它清空写队列
#【可能完全清空,也可能清空到某个程度】 在这个write drain的过程中,内存总线只能服务写操作,
#另外,切换进入或者离开write drain模式会对DRAM协议造成一定开销,
#这叫做(called read-to-write and write-to-read turnaround delays, tRTW and tWTR,
#approximately 7.5ns and 15ns, respectively [A case for exploiting subarray-level parallelism (SALP) in DRAM] )
#在这个过程中读写操作都不能调度使用总吸纳,造成浪费珍贵的总线资源,所以频繁的切换到write drain模式,
#或者在write drain模式中很长时间会对读操作造成很大的开销,这对于读密集的应用以及整个系统的性能影响很大。
yield from writer.drain()
while True:
line = yield from reader.readline()
if line == b'\r\n':
break
print('%s header > %s' %(host, line.decode('utf-8').rstrip()))
writer.close()
loop = asyncio.get_event_loop()
task = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop.run_until_complete(asyncio.wait(task))
loop.close()
wget www.sina.com.cn...
<generator object open_connection at 0x000001CA75C0FD58>
wget www.sohu.com...
<generator object open_connection at 0x000001CA75C0FEB8>
wget www.163.com...
<generator object open_connection at 0x000001CA75C30830>
www.sina.com.cn header > HTTP/1.1 200 OK
www.sina.com.cn header > Server: nginx
www.sina.com.cn header > Date: Thu, 05 Apr 2018 06:18:35 GMT
www.sina.com.cn header > Content-Type: text/html
www.sina.com.cn header > Content-Length: 604317
www.sina.com.cn header > Connection: close
www.sina.com.cn header > Last-Modified: Thu, 05 Apr 2018 06:15:10 GMT
www.sina.com.cn header > Vary: Accept-Encoding
www.sina.com.cn header > X-Powered-By: shci_v1.03
www.sina.com.cn header > Expires: Thu, 05 Apr 2018 06:19:10 GMT
www.sina.com.cn header > Cache-Control: max-age=60
www.sina.com.cn header > Age: 14
www.sina.com.cn header > Via: http/1.1 ctc.ningbo.ha2ts4.97 (ApacheTrafficServer/6.2.1 [cHs f ]), http/1.1 ctc.qingdao.ha2ts4.26 (ApacheTrafficServer/6.2.1 [cHs f ])
www.sina.com.cn header > X-Via-Edge: 1522909115032f7ef502a3105f98c2e1d1ca0
www.sina.com.cn header > X-Cache: HIT.26
www.sina.com.cn header > X-Via-CDN: f=edge,s=ctc.qingdao.ha2ts4.21.nb.sinaedge.com,c=42.80.239.247;f=Edge,s=ctc.qingdao.ha2ts4.26,c=140.249.5.21
www.sohu.com header > HTTP/1.1 200 OK
www.sohu.com header > Content-Type: text/html;charset=UTF-8
www.sohu.com header > Connection: close
www.sohu.com header > Server: nginx
www.sohu.com header > Date: Thu, 05 Apr 2018 06:18:24 GMT
www.sohu.com header > Cache-Control: max-age=60
www.sohu.com header > X-From-Sohu: X-SRC-Cached
www.sohu.com header > Content-Encoding: gzip
www.sohu.com header > FSS-Cache: HIT from 4396083.6951997.5576282
www.sohu.com header > FSS-Proxy: Powered by 4592694.7345216.5772896
www.163.com header > HTTP/1.0 302 Moved Temporarily
www.163.com header > Server: Cdn Cache Server V2.0
www.163.com header > Date: Thu, 05 Apr 2018 06:18:35 GMT
www.163.com header > Content-Length: 0
www.163.com header > Location: http://www.163.com/special/0077jt/error_isp.html
www.163.com header > Connection: close
asyncio
提供了完善的异步IO支持;
异步操作需要在coroutine
中通过yield from
完成;
多个coroutine
可以封装成一组Task然后并发执行