协程

协程概念

进程:资源单位,占用的是内存空间

线程:执行单位,CPU直接执行的最小单位

上面两个都是直接受到操作系统的控制,CPU在操作这些的时候,遇到io会切换,一个程序占用时间过长也会切换,那么为了实现将CPU的效率提升到最高,使用的方式就是并发,多个程序看起来像是一起进行的就是并发,并发的本质就是切换+保存状态

协程:就是在单线程的情况下,让多个任务实现并发的效果(切换+保存状态)

如何做到切换+保存状态呢?yield好像可以实现切换+保存状态

import time
def add():
    for i in range(100000):
        i+=1
        yield

def com():
    a=add()
    for x in range(10):
        x+1
        time.sleep(2)#20.00367259979248
        next(a)
start=time.time()
com()

print(time.time()-start
import time
def add():
    for i in range(100000):
        i+=1
        yield

def com():
    a=add()
    for x in range(10):
        x+1
        # time.sleep(2)#20.00367259979248
        next(a)
start=time.time()
com()

print(time.time()-start)  #19.555817365646362

这个并不能实现检测io行为,有一个模块可以帮助我们实现检测io行为,就是gevent模块


from gevent import monkey;monkey.patch_all()#监测所有io行为

from gevent import spawn

import time
def play(name):
print('%s is play iphone'%name)

time.sleep(2)模拟网络延迟时间

print('%s is playing '%name)

def eat(name):
print('%s is eating'%name)
time.sleep(5)模拟网络延迟时间
print('%s is eat'%name)
start= time.time()

# play('egon')
# eat('egon')
g1=spawn(play,'egon') 提交任务,提交完就不管了

g2=spawn(eat,'egon')
g1.join()所以要让上面的所有线程结束才可以
g2.join()
print(time.time()-start)直接打印的话就直接结束
 

gevent实现了单线程下实现了自动监测io,基于这个我们可以尝试着做到利用这一个实现单线程下抗住并发进程的攻击,以socket通信为例

#单线程下实现高并发,
import socket

from gevent import monkey;monkey.patch_all()
from gevent import spawn


def communicate(conn):#只用来通信
    while True:
        try:

            data = conn.recv(1024)
            if len(data) == 0: break
            print(data)
            conn.send(data.upper())

            pass
        except ConnectionResetError:
            break
    conn.close()

def server(ip,port):#只用来建立连接
    server = socket.socket()

    server.bind((ip,port))

    server.listen(5)
    while True:
        conn,addr=server.accept()

        # print(addr)
        spawn(communicate,conn)

if __name__ == '__main__':
    g1=spawn(server,'127.0.0.1',8090)
    g1.join()

客户端

import socket
from threading import Thread,current_thread



def clients():
    client = socket.socket()
    client.connect(('127.0.0.1', 8090))
    n=1
    while True:
        # info=input('>>:').strip().encode('utf-8')
        # if len(info)==0:continue
        data='%s %s'%(current_thread().name,n)
        n+=1
        client.send(data.encode('utf-8'))
        data=client.recv(1024)
        print(data)


if __name__ == '__main__':
    # p_list=[]
    for i in range(10):
        p=Thread(target=clients)
        p.start()
        # p_list.append(p)
    # for p in p_list:
    #     p.join()
原文地址:https://www.cnblogs.com/mcc61/p/10848899.html