21. Week 7 - Network programming - selectors module for IO multiplexing (single thread supports tens of thousands of concurrency)

  The selectors module in Python allows building advanced and efficient I/O multiplexing over selector module primitives. Select the best IO multiplexing mechanism according to the platform. For example, on the win system, it defaults to select mode; on linux, it defaults to epoll. Three IO multiplexing mechanisms are supported: select\poll\epoll.

  The function is similar to the epoll of linux, or the select module, poll, etc.; realizes efficient I/O multiplexing, which is often used in non-blocking socket programming; briefly introduce this module, see the python documentation for more details: https://docs .python.org/3/library/selectors.html

1. The module defines an abstract base class of BaseSelector and its subclasses, including:

  • SelectSelector 
  • PollSelector
  • EpollSelector
  • DevpollSelector
  • KqueueSelector

There is also a DefaultSelector class, which is actually an alias of one of the above subclasses. It is automatically selected as the most effective Selector in the current environment, so it is usually used. 

2. The module defines two constants to describe the event Mask

  • EVENT_READ: Indicates readable; its value is actually 1;
  • EVENT_WRITE: Indicates writable; its value is actually 2;

3. The module defines a SelectorKey class. Generally, an instance of this class is used to describe the state of a registered file object. Several properties of this class are commonly used:

  • fileobj: Represents a registered file object;
  • fd: Denotes the descriptor of the file object, which is an integer, which is the return value of the fileno() method of the file object;
  • events: Indicates whether the events we are waiting for when registering a file object, that is, the event Mask above, is readable or writable! !
  • data: Indicates that registering a file object is bound data;

4. Talk about the methods in the abstract base class:

register(fileobj, events, data=None) Function: Register a file object.
                                          Parameters: fileobj - either fd or an object with a fileno() method; events - the event Mask constant above; data return value: an instance of the SelectorKey class;

unregister(fileobj) function: unregister a registered file object;      
                                          Return value: an instance of the SelectorKey class;

modify(fileobj, events, data=None) Function: used to modify a registered file object, such as changing from monitor readable to monitor writable; it is actually register() followed by unregister(), but use modify() ) is more efficient;
									      Return value: an instance of the SelectorKey class;

select(timeout=None) function: used to select the file object that satisfies the event we are listening to;
                                          Return value: is a tuple of (key, events), where key is an instance of the SelectorKey class, and events is the event Mask (EVENT_READ or EVENT_WRITE, or a combination of the two)

close() function: close the selector. Finally, be sure to call it to ensure that all resources are released;

get_key(fileobj) Function: Return the key of the registered file object;
                                          Return value: an instance of the SelectorKey class

Example:

Server:

import selectors
import socket

class Server(object):
    def __init__(self,sel,sock):
        self.sel = sel
        self.sock = sock

    def run(self,host,port):
        self.sock.bind((host,port))
        self.sock.listen(1000)
        self.sock.setblocking(False)
        self.sel.register(self.sock,selectors.EVENT_READ,self.accept)
        while True:
            events = self.sel.select() #Blocked by default, if there is an active connection, it will return to the list of active connections
            print(events)
            for key,mask in events:
                callback = key.data
                callback(key.fileobj,mask)

    def accept(self,sock,mask):
        conn,addr = sock.accept()
        print("acceptd",conn,"from",addr)
        conn.setblocking(False)
        sel.register(conn,selectors.EVENT_READ,self.read)

    def read(self,conn,mask):
        data = conn.recv(1024)
        if data:
            print("echo",repr(data),"to",conn)
            conn.send(data)
        else:
            print("closing",conn)
            sel.unregister(conn)
            conn.colse()


if __name__ == "__main__":
    sel = selectors.DefaultSelector()
    sock = socket.socket()
    host,port = 'localhost',10006
    server_obj = Server(sel,sock)
    server_obj.run(host,port)

Client:

import socket

client = socket.socket()
client.connect(("localhost",10006))

while True:
    msg = bytes(input(">>:").strip(),encoding="utf-8")
    if len(msg) == "q".encode("utf-8"): exit("退出!")
    client.sendall(msg)
    data = client.recv(1024)
    print("recv:", data.decode())

client.close()

 

Guess you like

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