Concurrent programming---IO model

IO model

There are two ways to submit tasks:

  • Synchronization: The application submits the task, waits for the result, and then executes the next task
  • Asynchronous: After the application submits the task, it continues to execute without waiting for the result. After the task is executed, it will automatically start the asynchronous function.

Synchronization does not equal blocking:

  • Synchronization: After submitting the task, no matter whether the task is blocked or not, just wait for the received result, and then go down after the task runs.
  • Blocking: When IO is encountered when submitting a task, if it is not processed, the operating system will take away the CPU. Solution: use gevent, when IO is detected, switch to other tasks

The main classification of IO model:

  • blocking IO blocking IO
  • nonblocking IO nonblocking IO
  • IO multiplexing IO multiplexing
  • Signal driven IO signal driven IO 
  • Asynchronous IO asynchronous IO

Encountered IO will block: stuck in place;  network IO: blocked in place

1. What kind of operation on the server side belongs to IO behavior    

  • server-side accept, recv, send,
  • Among them accept, recv will feel obvious, etc.,
  • send doesn't obviously wait, but is also IO behavior

2. Why does IO behavior have the effect of waiting in place

      Because the server will have a waiting time when recv, it is waiting for the data in the operating system cache before copying it to the application program

blocking IO

import socket
from threading import Thread

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

def communicate():
    while True:
        try:
            data = conn.recv(1024 )
             print ( ' Received data: ' ,data)
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()

print('setting...')
while True:
    print('settings')
    conn,client_addr = server.accept() # io is blocked, the operating system takes away the cpu 
    print (client_addr)

    t = Thread(target=communicate,args=(conn,))
    t.start()

server.close()
Server
import socket
client = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1',8080))

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

non-blocking IO

The application detects io by itself, and when it encounters io, it switches to other tasks, which can greatly improve the efficiency of single thread

Existing problems:

  • When the cpu is doing other things, the data is sent, and it will not respond immediately
  • There is no blocking on the server side, it is an infinite loop, the cpu will always run, and the process is in a ready state, which takes up a lot of cpu, so that the application program keeps asking the operating system whether the data is good or not, doing useless work

Multiplexed IO

Blocking io: there are wait() waiting process, copy process,

Multiplexing io: There is one more select process than blocking io. This process can be used as an intermediary to ask the operating system for data

  • Disadvantages: When there is only one socket, the performance is lower than that of blocking io. When monitoring multiple sockets, the cycle is slow. If there is a lot of list data, the efficiency is low.
  • Advantages: When there are multiple sockets, it can be handed over to select for processing, which has higher performance than blocking io

elect : list looping is inefficient

poll : The list data that can be received is not very efficient

epoll: the highest efficiency, bind a callback function to each socket through asynchronous operation, whoever is better will trigger the callback, (there is no need to traverse the inefficiency)

epoll: windows does not have; linux has

The selectors module automatically selects based on the operating system

 

import socket
import select
server = socket.socket (socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1',8080))
server.listen(5)
server.setblocking(False)
print('settings')

rlist=[server,] #存收的套接字,有两种:conn        ,server
wlist=[] #存发的套接字
wdata={}

while True:
    rl,wl,xl = select.select(rlist,wlist,[],0.5) #去向操作系统问套接字准备好没有,异常列表[] m每隔0.5秒问一次
    print('rl',rl)
    print('wl',wl)

    for sock in rl:
        if sock == server:
            conn,addr = sock.accept()
            rlist.append(conn)
        else:
            try: #适用于windows系统
                data = sock.recv(1024)
                if not data: #适用于linux系统,会一直收空
                    sock.close()
                    rlist.remove(sock)
                    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()
服务端

 

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

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

phone.close()
客户端

 

Guess you like

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