Python aprendiendo multiplexación de E/S

1. Concepto de multiplexación de E/S:

Monitoree el estado de múltiples descriptores.Si el estado del descriptor cambia, el kernel modificará el bit de bandera, que será obtenido por el proceso para operaciones de lectura y escritura.

二, seleccionar, encuesta, epoll

El módulo de selección proporciona tres métodos: select, poll y epoll, que llaman a select, poll y epoll del sistema respectivamente para lograr la multiplexación IO.

Windows Python: Proporciona: seleccionar

Mac Python: Proporciona: seleccionar

Linux Python: proporciona: seleccionar, sondear, epoll

seleccionar

En Python, la función de selección es una interfaz que accede directamente al sistema operativo subyacente y se utiliza para monitorear sockets, archivos y tuberías y esperar a que se complete IO. Select puede monitorear fácilmente cuándo ocurren eventos legibles, escribibles o anormales.

Actualmente, Select es compatible con casi todas las plataformas y su buen soporte multiplataforma también es una de sus ventajas, y también es una de las pocas ventajas que le quedan.

Una desventaja de select es que existe un límite máximo en la cantidad de descriptores de archivos que un solo proceso puede monitorear, que generalmente es 1024 en Linux, pero este límite se puede aumentar modificando la macro.

Formato:rList,wList,eList = select.select(argv1,argv2,argv3,timeout)

parámetro:

argv1: cuando cambia el identificador en la secuencia de escucha, el identificador modificado se obtiene y se agrega a la secuencia rList.

argv2: cuando la secuencia de escucha contiene identificadores, agregue todos los identificadores de la secuencia a la secuencia wList.

argv3: cuando ocurre un error en el identificador de la secuencia de escucha, el identificador de error se agregará a la secuencia eList.

tiempo de espera: establece el tiempo de bloqueo, si no se establece, se bloqueará de forma predeterminada.

seleccione ejemplo:

Uso de select para manejar múltiples solicitudes de clientes de socket

Servidor

#!/usr/bin/env pitón

# -*- codificación:utf-8 -*-

conector de importación

importar seleccionar

puerto_ip = ("127.0.0.1",9999)

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Crear objeto de socket

sk.bind(ip_port) #Vincular ip, puerto

sk.listen(5) #Escucha

sk.setblocking (Falso) #Sin bloqueo

entradas = [sk,]

salidas = []

mientras que Verdadero:

rlist,wlist,eList = select.select(entradas,salidas,[],0.5)

print("entradas:",entradas) #Ver cambios en la lista de entradas

print("rlist:",rlist) #Ver cambios en la lista rlist

para r en rlista:

if r == sk: #Si r es el servidor

conexión, dirección = r.accept()#

entradas.append(conexión)

imprimir (dirección)

demás:

datos_cliente = r.recv(1024)

if client_data: #Si hay datos, devuelve los datos

r.sendall(datos_cliente)

else: # De lo contrario eliminar

entradas.eliminar(r)

Cliente:

#!/usr/bin/env pitón

# -*- codificación:utf-8 -*-

conector de importación

puerto_ip = ("127.0.0.1",9999)

sk = socket.socket() #Crear objeto de socket

sk.connect(ip_port) #Conectarse al servidor a través de ip y puerto

mientras que Verdadero:

entrada=entrada(">>:")

sk.sendall(bytes(inpu,"utf8")) #Enviar información al servidor

server_reply = sk.recv(1024) #Aceptar mensaje

print (str(server_reply,"utf8")) #Imprimir mensaje

sk.close() #Cerrar la conexión

proceso:

Inicie el servidor. En este momento, select seguirá escuchando el identificador del servidor hasta que llegue una solicitud del cliente y cambie.

Cuando proviene una nueva solicitud de conexión del cliente, select captura el cambio en el identificador del servidor y agrega el identificador modificado a rlist, por lo que en este momento r == sk, recibe el enlace y agrega el identificador a la lista de entradas.

Ahora, seleccione escucha dos identificadores. De la misma manera, cuando lleguen varias solicitudes de enlace, se agregarán a la lista de entradas.

Cuando uno de los clientes A envía información, select capturará el cambio en el identificador del cliente A en la lista de identificadores monitoreados y agregará el identificador modificado a rlist, pero en este momento r no es igual a sk.

Realice otro paso para recibir los datos de devolución.

Lo anterior mencionó una descripción general del parámetro argv1, que es monitorear la lista argv1. Cuando ocurran cambios, se capturará y agregará a rlist.

Parámetro argv2: siempre que haya un valor en esta lista, se agregará a wList cada vez, a diferencia de argv1

Por lo tanto, puede utilizar el parámetro argv2 para lograr la separación de lectura y escritura.

lado del servidor

#!/usr/bin/env pitón

# -*- codificación:utf-8 -*-

conector de importación

importar seleccionar

cola de importación

puerto_ip = ("127.0.0.1",9999)

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Crear objeto de socket

sk.bind(ip_port) #Vincular ip, puerto

sk.listen(5) #Escucha

sk.setblocking (Falso) #Sin bloqueo

entradas = [sk,]

salidas = []

mensaje={}

mientras que Verdadero:

rlist,wlist,eList = select.select(entradas,salidas,[],0.5)

#print("inputs:",inputs) #Ver cambios en la lista de entradas

#print("rlist:",rlist) #Ver cambios en la lista rlist

#imprimir(mensaje)

para r en rlista:

if r == sk: #Si r es el servidor

conexión, dirección = r.accept()#

inputs.append(conn) #Agregar el identificador de conexión a la lista de entradas para monitoreo

message[conn] = queue.Queue() #Cada nuevo identificador corresponde a una cola

imprimir (dirección)

demás:

datos_cliente = r.recv(1024)

if client_data: #Si hay datos, devuelve los datos

salidas.append(r)

mensaje[r].put(client_data) #Insertar datos en la cola especificada

demás:

inputs.remove(r) #de lo contrario eliminar

del mensaje[r] #eliminar cola

para w en wlist: #Si la lista wlist tiene un valor

intentar:

data =message[w].get_nowait()#Vaya a la cola especificada para obtener datos

w. sendall(datos)

excepto cola. Vacío:

aprobar

outputs.remove(w)# Debido a que la lista de salida se agregará a la lista wlist cada vez que haya datos, los datos deben eliminarse después de enviarlos.

En la lista de escucha de argv3, si ocurre un error durante el proceso de comunicación con una determinada conexión de socket, se agregará el identificador incorrecto a la eList, por lo que se agrega un juicio. Cuando ocurre un error durante el proceso de comunicación con un determinado socket conexión, elimine este objeto de conexión incorrecto de varias listas y diccionarios.

Agregar un juicio en el bucle

para e en eList:

inputs.remove(e)#Eliminar el identificador de error del monitoreo de entradas

si e en salidas:#Si hay uno en salidas, elimínelo también

salidas.remove(e)

e.cerrar()

del mensaje[e] #eliminar cola

Una vez introducidos los cuatro parámetros de selección, se adjunta el código completo en el lado del servidor.

#!/usr/bin/env pitón

# -*- codificación:utf-8 -*-

conector de importación

importar seleccionar

cola de importación

puerto_ip = ("127.0.0.1",9999)

sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #Crear objeto de socket

sk.bind(ip_port) #Vincular ip, puerto

sk.listen(5) #Escucha

sk.setblocking (Falso) #Sin bloqueo

entradas = [sk,]

salidas = []

mensaje={}

mientras que Verdadero:

rlist,wlist,eList = select.select(entradas,salidas,entradas,0.5)

#print("inputs:",inputs) #Ver cambios en la lista de entradas

#print("rlist:",rlist) #Ver cambios en la lista rlist

#imprimir(mensaje)

para r en rlista:

if r == sk: #Si r es el servidor

conexión, dirección = r.accept()#

inputs.append(conn) #Agregar el identificador de conexión a la lista de entradas para monitoreo

message[conn] = queue.Queue() #Cada nuevo identificador corresponde a una cola

imprimir (dirección)

demás:

datos_cliente = r.recv(1024)

if client_data: #Si hay datos, devuelve los datos

salidas.append(r)

mensaje[r].put(client_data) #Insertar datos en la cola especificada

demás:

inputs.remove(r) #de lo contrario eliminar

del mensaje[r] #eliminar cola

para w en wlist: #Si la lista wlist tiene un valor

intentar:

data =message[w].get_nowait()#Vaya a la cola especificada para obtener datos

w. sendall(datos)

excepto cola. Vacío:

aprobar

outputs.remove(w)# Debido a que la lista de salida se agregará a la lista wlist cada vez que haya datos, los datos deben eliminarse después de enviarlos.

para e en eList:

inputs.remove(e)#Eliminar el identificador de error del monitoreo de entradas

si e en salidas:#Si hay uno en salidas, elimínelo también

salidas.remove(e)

e.cerrar()

del mensaje[e] #eliminar cola

Reimpreso de: Weidian Reading    https://www.weidianyuedu.com

Supongo que te gusta

Origin blog.csdn.net/hdxx2022/article/details/132636386
Recomendado
Clasificación