Chapter 7 | Concurrent Programming | The I/O Model

I/O model

Coroutines are concurrency under a single thread, which does not improve performance. It must detect the I/O of multiple tasks under a single thread. Do not let it block when encountering I/O, and automatically switch to other tasks. Go; this can improve the operating efficiency under a single thread. The gevent module is used to implement it. How does gevent detect I/O behavior and automatically switch to other tasks when encountering I/O.

Synchronous and asynchronous, a synchronous call is to run the downlink code after submitting the task and wait for the result to get the result; an asynchronous call is to ignore it after submitting and then execute it. Asynchrony is usually used in conjunction with the callback mechanism. After I submit a task, this After the task runs, it will automatically trigger the callback function to run and hand over the result to it.

Synchronization is not necessarily blocking.

 

blocking I/O

#Blocking I/ O has no concurrency, just wait when blocked
 from socket import *
 from threading import Thread #Multi-threading can be used to achieve concurrency
def communicate(conn):
    while True:
        try:
            data = conn.recv(1024) #等待
            if not data: break
            conn.send(data.upper())
        except ConnectionResetError:
            break

    conn.close()

server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    print('starting...')
    conn, addr = server.accept() #wait stage is mainly stuck here
    print(addr)

    t =Thread(target=communicate,args=(conn,)) #Let the main thread do the accept work, and each link initiates a thread to let it do the communication work; I/ O blocking is not solved, and each operation does not affect each other
    t.start() #Thread pool ensures that the machine runs in a healthy state

server.close()
from socket import *

client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8080))

while True:
    msg=input('>>: ').strip()
    if not msg:continue
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))
client.close()

Non-blocking I/O

Monitor I/O under a single thread and help you automatically switch to another task

How are the wait and copy stages handled?

Same as gevent.

from socket import *

server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8083))
server.listen(5)
server.setblocking(False) #True is blocking, False is non-blocking
print('starting...')

rlist=[]
wlist = [] #send will also block when there is a large amount of data
 while True:
     try :
        conn, addr = server.accept() #Ask ​​the operating system for data; the server can keep building links
        rlist.append(conn)
        print(rlist)
    except BlockingIOError: #Catch this exception
        #print( ' Do other work ' ) #You can do other work without data,

        #Receive message
        del_rlist = []
        for conn in rlist:
            try:
                data=conn.recv(1024)
                if not data:
                    del_rlist.append(conn)
                    continue
                wlist.append((conn,data.upper())) #Store the socket and the data to be sent
            except BlockingIOError:
                continue
            except Exception:
                conn.close()
                del_rlist.append(conn)

        #send message
        del_wlist=[]
        for item in wlist:
            try:
                conn=item[0]
                data=item[1]
                conn.send(data)
                del_wlist.append(item)
            except BlockingIOError: #
                pass

        for item in del_wlist:#Successfully sent and deleted you
            wlist.remove(item)

        for conn in del_rlist: #Delete the conn that has no data sent
            rlist.remove(conn)


server.close()

 

from socket import *

client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8083))

while True:
    msg=input('>>: ').strip()
    if not msg:continue
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))

client.close()

 

Multiplexed I/O Model

from socket import *
import select

server = socket (AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1',8083))
server.listen(5)
server.setblocking(False)
print('starting...')

rlist = [server,] #Specially store messageswlist = [] 
#Stored data
wdata = {}

while True:
    rl,wl,xl = select . select (rlist,wlist,[], 0.5 ) #Ask ​​the operating system; [] indicates an abnormal
    print( ' rl ' ,rl) #rlist will keep a bunch of conn and server; wlist will keep a bunch of conn, once the buffer is not full, it can be sent
    print( ' wl ' ,wl) #wl is a socket that can send values ​​to the buffer

    for sock in rl:
         if sock == server: #do the link work
            conn,addr=sock.accept()
            rlist.append(conn)
        else:
            try:
                data =sock.recv( 1024 )
                 if not data: #For linux system
                    sock.close()
                    rlist.remove(sock) #Do not monitor this socket
                    continue
                wlist.append(sock)
                wdata[sock]=data.upper()
            except Exception:
                sock.close()
                rlist.remove(sock) ##

    for sock in wl:
        data=wdata[sock]
        sock.send(data)
        wlist.remove(sock)
        wdata.pop(sock)

server.close()

 

from socket import *

client = socket (AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1',8083))

while True:
    msg=input('>>: ').strip()
    if not msg:continue
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))

client.close()

 

Asynchronous I/O Model

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324741878&siteId=291194637