• IO多路复用三种方式select/poll/epoll


    select多并发socket例子:

    #_*_coding:utf-8_*_
    __author__ = 'Alex Li'
    
    import select
    import socket
    import sys
    import queue
    
    
    server = socket.socket()
    server.setblocking(0)
    
    server_addr = ('localhost',10000)
    
    print('starting up on %s port %s' % server_addr)
    server.bind(server_addr)
    
    server.listen(5)
    
    
    inputs = [server, ] #自己也要监测呀,因为server本身也是个fd
    outputs = []
    
    message_queues = {}
    
    while True:
        print("waiting for next event...")
    
        readable, writeable, exeptional = select.select(inputs,outputs,inputs) #如果没有任何fd就绪,那程序就会一直阻塞在这里
    
        for s in readable: #每个s就是一个socket
    
            if s is server: #别忘记,上面我们server自己也当做一个fd放在了inputs列表里,传给了select,如果这个s是server,代表server这个fd就绪了,
                #就是有活动了, 什么情况下它才有活动? 当然 是有新连接进来的时候 呀
                #新连接进来了,接受这个连接
                conn, client_addr = s.accept()
                print("new connection from",client_addr)
                conn.setblocking(0)
                inputs.append(conn) #为了不阻塞整个程序,我们不会立刻在这里开始接收客户端发来的数据, 把它放到inputs里, 下一次loop时,这个新连接
                #就会被交给select去监听,如果这个连接的客户端发来了数据 ,那这个连接的fd在server端就会变成就续的,select就会把这个连接返回,返回到
                #readable 列表里,然后你就可以loop readable列表,取出这个连接,开始接收数据了, 下面就是这么干 的
    
                message_queues[conn] = queue.Queue() #接收到客户端的数据后,不立刻返回 ,暂存在队列里,以后发送
    
            else: #s不是server的话,那就只能是一个 与客户端建立的连接的fd了
                #客户端的数据过来了,在这接收
                data = s.recv(1024)
                if data:
                    print("收到来自[%s]的数据:" % s.getpeername()[0], data)
                    message_queues[s].put(data) #收到的数据先放到queue里,一会返回给客户端
                    if s not  in outputs:
                        outputs.append(s) #为了不影响处理与其它客户端的连接 , 这里不立刻返回数据给客户端
    
    
                else:#如果收不到data代表什么呢? 代表客户端断开了呀
                    print("客户端断开了",s)
    
                    if s in outputs:
                        outputs.remove(s) #清理已断开的连接
    
                    inputs.remove(s) #清理已断开的连接
    
                    del message_queues[s] ##清理已断开的连接
    
    
        for s in writeable:
            try :
                next_msg = message_queues[s].get_nowait()
    
            except queue.Empty:
                print("client [%s]" %s.getpeername()[0], "queue is empty..")
                outputs.remove(s)
    
            else:
                print("sending msg to [%s]"%s.getpeername()[0], next_msg)
                s.send(next_msg.upper())
    
    
        for s in exeptional:
            print("handling exception for ",s.getpeername())
            inputs.remove(s)
            if s in outputs:
                outputs.remove(s)
            s.close()
    
            del message_queues[s]
    select socket server
    #_*_coding:utf-8_*_
    __author__ = 'Alex Li'
    
    
    import socket
    import sys
    
    messages = [ b'This is the message. ',
                 b'It will be sent ',
                 b'in parts.',
                 ]
    server_address = ('localhost', 10000)
    
    # Create a TCP/IP socket
    socks = [ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              socket.socket(socket.AF_INET, socket.SOCK_STREAM),
              ]
    
    # Connect the socket to the port where the server is listening
    print('connecting to %s port %s' % server_address)
    for s in socks:
        s.connect(server_address)
    
    for message in messages:
    
        # Send messages on both sockets
        for s in socks:
            print('%s: sending "%s"' % (s.getsockname(), message) )
            s.send(message)
    
        # Read responses on both sockets
        for s in socks:
            data = s.recv(1024)
            print( '%s: received "%s"' % (s.getsockname(), data) )
            if not data:
                print(sys.stderr, 'closing socket', s.getsockname() )
    select socket client

    selectors模块

    This module allows high-level and efficient I/O multiplexing, built upon the select module primitives. Users are encouraged to use this module instead, unless they want precise control over the OS-level primitives used.

    import selectors
    import socket
     
    sel = selectors.DefaultSelector()
     
    def accept(sock, mask):
        conn, addr = sock.accept()  # Should be ready
        print('accepted', conn, 'from', addr)
        conn.setblocking(False)
        sel.register(conn, selectors.EVENT_READ, read)
     
    def read(conn, mask):
        data = conn.recv(1000)  # Should be ready
        if data:
            print('echoing', repr(data), 'to', conn)
            conn.send(data)  # Hope it won't block
        else:
            print('closing', conn)
            sel.unregister(conn)
            conn.close()
     
    sock = socket.socket()
    sock.bind(('localhost', 10000))
    sock.listen(100)
    sock.setblocking(False)
    sel.register(sock, selectors.EVENT_READ, accept)
     
    while True:
        events = sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import selectors
    import socket
     
    sel = selectors.DefaultSelector()
     
    def accept(sock, mask):
        conn, addr = sock.accept()  # Should be ready
        print('accepted', conn, 'from', addr)
        conn.setblocking(False)
        sel.register(conn, selectors.EVENT_READ, read)
     
    def read(conn, mask):
        data = conn.recv(1000)  # Should be ready
        if data:
            print('echoing'repr(data), 'to', conn)
            conn.send(data)  # Hope it won't block
        else:
            print('closing', conn)
            sel.unregister(conn)
            conn.close()
     
    sock = socket.socket()
    sock.bind(('localhost'10000))
    sock.listen(100)
    sock.setblocking(False)
    sel.register(sock, selectors.EVENT_READ, accept)
     
    while True:
        events = sel.select()
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)
  • 相关阅读:
    python lambda函数的用法
    python 中is 和 ==的区别
    Mongo 聚合函数 $group方法的使用
    mongo聚合
    当mongo数据库报错关于 Failed global initialization:
    python 中字符串的拼接
    python eval()用法报错 SyntaxError: unexpected EOF while parsing
    高性能MySQL(六):选择合适的存储引擎
    高性能MySQL(五):存储引擎
    高性能MySQL(四):多版本并发控制
  • 原文地址:https://www.cnblogs.com/staff/p/9710675.html
Copyright © 2020-2023  润新知