Overview:
- I/O multiplexing enables programs to be registered with the Operating System kernel for them to be notified of one or more I/O conditions.
- Programs often use I/O multiplexing when the number of descriptors involved is more. Example: A server program handling multiple sockets.
- The select module of Python provides low level I/O multiplexing routines provided by most of the operating systems, like select() and poll().
- The module also provides methods that are specific to certain operating systems like Solaris and BSD.
Example - Using select for I/O multiplexing in Python:
Echo Client:
import socket import select # For I/O multiplexing import sys
def readServerWriteToStdOut(socketDesc): data = socketDesc.recv(1024) #print("Received from Server: %s"%(data)) print(data)
def readStdInWriteToServer(inputDesc,data2Svr): bytes = str.encode(data2Svr) inputDesc.sendall(bytes)
# Create a socket instance echoSocket = socket.socket()
# Obtain the descriptor of the socket socketDesc = echoSocket.fileno()
# Obtain the descriptor of the standard input inputDesc = sys.stdin.fileno()
# Using the socket connect to the echo server...in this case localhost echoSocket.connect(("localhost", 32768)) print("Connected to echo server at local host")
readDescriptors = [] readDescriptors.append(socketDesc) readDescriptors.append(inputDesc)
writeDescriptors = [] execptionDescriptors = [] try: while(True): readReady, writeReady, exceptionReady = select.select(readDescriptors, writeDescriptors, execptionDescriptors)
for desc in readReady: if desc is socketDesc: data = readServerWriteToStdOut(echoSocket) break
if desc is inputDesc: data2Svr = input() readStdInWriteToServer(echoSocket,data2Svr) break except KeyboardInterrupt: echoSocket.shutdown(socket.SHUT_RDWR) echoSocket.close() pass |
Echo Server:
import socket import os
# Create a server socket for the echo server serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Server socket for echo server created")
# Associate the server socket of the echo server with the IP address and Port ipAddress = "127.0.0.1" portNumber = 32768
serverSocket.bind((ipAddress, portNumber)) print("Server socket bound with ip address {} on port {}".format(ipAddress, portNumber))
# Make the echo server listen for incoming connections serverSocket.listen()
# Serve the incoming connections echoCount = 0
try: while(True): (clientConnection, clientAddress) = serverSocket.accept() echoCount = echoCount + 1 print("Echo server has served {} connections so far".format(echoCount))
# Read the data sent by echo clients while(True): data = clientConnection.recv(1024) print(data) if(data == b''): clientConnection.close() break; sent = clientConnection.sendall(data) clientConnection.close() print("Connection closed for ip address {}".format(clientAddress))
except KeyboardInterrupt: pass
finally: serverSocket.close()
|
Example-Using select to send to and receive from a HTTP Server in Python:
# import the socket and select modules import socket import select
# List of descriptors for - Read, Write and Exception rlist = [] wlist = [] xlist = []
# Create a socket instance socketObject = socket.socket()
# Get the descriptor of the socket object and add to write descriptor list socketDescriptor = socketObject.fileno() wlist.append(socketDescriptor)
# Connect to example.com socketObject.connect(("example.com", 80)) print("Connected to example.com")
# Use select and block till the descriptor is ready for write readReady, writeReady, exceptionOccurred = select.select(rlist, wlist, xlist,0)
# Send a http message to example.com and get the home page if writeReady[0] is socketDescriptor: HTTPMessage = "GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n" httpMessageBytes = str.encode(HTTPMessage) socketObject.sendall(httpMessageBytes)
# Create a new list # Removing from wlist and adding to rlist will also work # However, one can not add the same descriptor to two lists - rlist and wlist rlist1 = [] wlist1 = [] xlist1 = [] rlist1.append(socketDescriptor)
# Use select and block till the descriptor is ready for read readReady, writeReady, exceptionOccurred = select.select(rlist1, wlist1, xlist1 )
# Make sure the descriptor is the one we are interested in if readReady[0] is socketDescriptor: # Receive the data while(True): data = socketObject.recv(1024) print(data)
if(data==b''): print("Connection closed") break
socketObject.close() |