---------------------------------------- 遇到io操作就切换 手动switch from greenlet import greenlet #协成 def test1(): print(12) gr2.switch() print(34) gr2.switch() #再切换2 def test2(): print(56) gr1.switch() print(78) gr1 = greenlet(test1) #启动一个协程 gr2 = greenlet(test2) gr1.switch() #手动切换 gevent 自动档 --------------------------------gevent(自动)---- import gevent def func1(): print('\033[31;1m在跟搞...\033[0m') gevent.sleep(2) print('\033[31;1m又回去跟继续跟搞...\033[0m') def func2(): print('\033[32;1m切换到了跟搞...\033[0m') gevent.sleep(1) print('\033[32;1m搞完了,回来继续跟海龙搞...\033[0m') gevent.joinall([ gevent.spawn(func1), gevent.spawn(func2), # gevent.spawn(func3), ]) --------------------------爬虫网页----------- import gevent,time from urllib.request import urlopen from gevent import monkey monkey.patch_all() #当前程序的io操作做标记 def f(url): print('GET: %s' % url) resp = urlopen(url) data = resp.read() # f=open("url.html","wb") # f.write(data) # f.close() 存到本地 print('%d bytes received from %s.' % (len(data), url)) urls=[ 'https://www.python.org/', 'https://www.yahoo.com/', 'https://github.com/' ] time_start=time.time() for url in urls: f(url) print("同步cost:",time.time()-time_start) async_time_start=time.time() gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'), gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://github.com/'), ]) print("异步cost",time.time()-async_time_start) --------------------server 协成-------io自动驱动--------------------- import sys import socket import time import gevent from gevent import socket, monkey monkey.patch_all() def server(port): s = socket.socket() s.bind(('0.0.0.0', port)) s.listen(500) while True: cli, addr = s.accept() #将请求交给一实例 创建一个线程 gevent.spawn(handle_request, cli) def handle_request(conn): try: while True: data = conn.recv(1024) print("recv:", data) conn.send(data) if not data: conn.shutdown(socket.SHUT_WR) except Exception as ex: print(ex) finally: conn.close() if __name__ == '__main__': server(8001) -------client----- import socket HOST = 'localhost' # The remote host PORT = 8001 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while True: msg = bytes(input(">>:"), encoding="utf8") s.sendall(msg) data = s.recv(1024) # print(data) print('Received', repr(data)) # 格式化输出 s.close() -------------------事件驱动与异步io----------- 通常,我们写服务器处理模型的程序时,有以下几种模型: (1)每收到一个请求,创建一个新的进程,来处理该请求; (2)每收到一个请求,创建一个新的线程,来处理该请求; (3)每收到一个请求,放入一个事件列表,让主进程通过非阻塞I/O方式来处理请求 --https://www.cnblogs.com/alex3714/articles/5876749.html---- ------- 当一个read操作发生时,它会经历两个阶段: 1. 等待数据准备 (Waiting for the data to be ready) 2. 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process) 正式因为这两个阶段,linux系统产生了下面五种网络模式的方案。 - 阻塞 I/O(blocking IO) - 非阻塞 I/O(nonblocking IO) - I/O 多路复用( IO multiplexing) - 信号驱动 I/O( signal driven IO) - 异步 I/O(asynchronous IO) 注:由于signal driven IO在实际中并不常用,所以我这只提及剩下的四种IO Model。 ---------------------------------------------------------- 异步io 星级服务 多路复用 (同步io) 最后read需要 wait-- -------------------- BSD:unix的分支 多路复用(以下方式 数据在内核里 user recv or read ) select() :监测socket链接 最多只能维护1024个socket poll: 65535限制 epoll:not support epoll (linux 2.6 core ) 返回数据时指定活跃的链接 没有最大端口数 一个1g内存数据 10万台服务器 一个链接4k aio 模块 支持异步io nginx:其实是io多路复用 python3.0 后 asyncio 模块:支持异步io http://www.cnblogs.com/alex3714/articles/4372426.html -------------------------------多路复用实用socket_Serer----(非阻塞状态)--- import select import socket import queue server = socket.socket() server.bind(('localhost',9000)) server.listen(100) server.setblocking(False) #设置为不阻塞 没有链接就报错 inputs=[server,] #监听自己 outputs=[] #输入 输出 报错 while True: readable,writeale,exceptional=select.select(inputs,outputs,inputs) print(readable,writeale,exceptional) for r in readable: if r is server: #如果是server 就有新链接 conn,addr=server.accept() print("来了个新链接",addr) inputs.append(conn) #现在数据不存在 ,无法接收 需要监测 input else: data=r.recv(1024) print("收到数据",data) r.send(data) print("send down....") server.accept() server.close() -------------- import socket HOST = 'localhost' # The remote host PORT = 9000 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while True: msg = bytes(input(">>:"), encoding="utf8") s.sendall(msg) # data = s.recv(1024) #不接受数据 # # print(data) # # print('Received', repr(data)) # 格式化输出 s.close() --------------------放 queue-下次再发---------------- import select import socket import queue server = socket.socket() server.bind(('localhost',9000)) server.listen(100) server.setblocking(False) #设置为不阻塞 没有链接就报错 msg_dic={} inputs=[server,] #监听自己 outputs=[] #输入 输出 报错 while True:#select 会返回三个值 readable,writeable,exceptional=select.select(inputs,outputs,inputs) print(readable,writeable,exceptional) for r in readable: if r is server: #如果是server 就有新链接 conn,addr=server.accept() print("来了个新链接",addr) inputs.append(conn) #现在数据不存在 ,无法接收 需要监测 input msg_dic[conn]=queue.Queue()#初始化一个队列 后面存要返回给客户端的数据 else: data=r.recv(1024) print("收到数据",data) msg_dic[r].put(data) outputs.append(r)#放入返回的链接队列里 # r.send(data) # print("send down....") for w in writeable: #返回的数据 data_to_client = msg_dic[w].get() w.send(data_to_client) #返回给客户端元数据 outputs.remove(w) #下次不返回 数据 了 for e in exceptional: if e in outputs: outputs.remove(e) inputs.remove(e) del msg_dic[e] server.close() ----------------- import socket HOST = 'localhost' # The remote host PORT = 9000 # The same port as used by the server s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while True: msg = bytes(input(">>:"), encoding="utf8") s.sendall(msg) data = s.recv(1024) print(data) # print('Received', repr(data)) # 格式化输出 s.close() ---------select模块 默认epoll------- import selectors import socket sel = selectors.DefaultSelector() def accept(sock, mask): conn, addr = sock.accept() # Should be ready print('accepted', conn, 'from', addr) conn.setblocking(False) sel.register(conn, selectors.EVENT_READ, read) def read(conn, mask): data = conn.recv(1000) # Should be ready if data: print('echoing', repr(data), 'to', conn) conn.send(data) # Hope it won't block else: print('closing', conn) sel.unregister(conn) conn.close() sock = socket.socket() sock.bind(('localhost', 10000)) sock.listen(100) sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) while True: events = sel.select() #默认是阻塞 for key, mask in events: callback = key.data callback(key.fileobj, mask) #没建立好的r $$$ulimit -n ulimit -SHn 65535 10天17。。。