网络编程和异步IO都有非常丰富的内容。这里只不过是非常简单的介绍。python的socket模块可以用来进行TCP/UDP协议的简单处理
- TCP协议负责在两台计算机之间建立可靠的链接,保证数据按顺序到达
- UDP协议不需要建立连接,不能保证数据到达性和顺序性
- 协程在执行过程中,子程序内部中断,然后转而去执行别的子程序,在适当的时候再返回来接着执行。类似CPU的中断
- 协程不是函数调用
- 协程通过yield和send函数进行协作
- 材料[A Curious Course on Coroutines and Concurrency](http://www.dabeaz.com/coroutines/index.html
- 对异步IO的支持
- @asyncio.coroutine装饰器
- yield from调用另一个coroutine
- get_event_loop()/run_until_complete()/await()
- @asyncio.coroutine换成asyncio
- yield from换成await
In [1]:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('www.sina.com.cn', 80))
s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n')
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b''.join(buffer)
s.close()
header, html = data.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
#Server
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' %)
In [ ]:
# server
import socket
import threading
import time
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' %addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' %data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' %addr)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', 9999))
s.listen(5)
print('Waiting for connection...')
while True:
sock, addr = s.accept()
t = threading.Thread(target=tcplink, args=(sock, addr))
t.start()
# client
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9999))
print(s.recv(1024).decode('utf-8'))
for data in [b'Michael', b'Tracy', b'Sarah']:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
In [ ]:
# UDP
# server
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('127.0.0.1', 9998))
print('Bind UDP on 9998')
while True:
data, addr = s.recvfrom(1024)
print('Received from %s:%s' %addr)
s.sendto(b'Hello, %s!' %data, addr)
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [b'Michael', b'Tracy', b'Sarah']:
s.sendto(data, ('127.0.0.1', 9998))
print(s.recv(1024).decode('utf-8'))
s.close()
In [1]:
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' %n)
r = '200 0k'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' %n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' %r)
c.close()
c = consumer()
produce(c)
In [1]:
import asyncio
import threading
@asyncio.coroutine
def hello():
print('Hello world!')
r = yield from asyncio.sleep(10)
print('Hello again!')
loop = asyncio.get_event_loop()
loop.run_until_complete(hello())
In [2]:
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! %s' %threading.currentThread())
yield from asyncio.sleep(5)
print('Hello world! %s' %threading.currentThread())
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
Out[2]:
In [5]:
import asyncio
@asyncio.coroutine
def wget(host):
print('wget %s...' %host)
connect = asyncio.open_connection(host, 80)
reader, writer = yield from connect
header = 'GET / HTTP/1.0/\r\nHost:%s\r\n\r\n' %host
writer.write(header.encode('utf-8'))
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()
tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]
loop.run_until_complete(asyncio.wait(tasks))
Out[5]:
In [ ]: