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