zoukankan      html  css  js  c++  java
  • python之路(16)IO模型、select模块、selectors模块

     目录

    • 阻塞IO
    • 非阻塞IO 

     阻塞IO

      当有数据传入传出的时候,接收方必须一致等待数据的接收才可以进行下一步操作,接收方(操作系统)必须等待数据,这个时候是一个阻塞的状态。在socket模块默认的情况下实现sever端就是一个阻塞IO例子

    非阻塞IO

      与阻塞IO相对的,在接收方等待数据的时候,如果对方没有发送数据,接收方可以进行后面的操作,等待对方将数据发送过来再进行执行之前的操作。具体实现在等待数据的时候,先执行后面的程序,按照一定的时间,反复的去查看,对方是否已经发送了数据。

      在socket模块也能实现实现sever端和client端非阻塞IO例子

    server端

    import time
    import socket
    sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    sk.bind(('127.0.0.1',6667))
    sk.listen(5)
    sk.setblocking(False) #开启非阻塞的状态
    print ('waiting client connection .......')
    
    while True:
        try:
            connection,address = sk.accept()   # 进程主动轮询
            print("+++",address)
            client_messge = connection.recv(1024)
            print(str(client_messge,'utf8'))
            connection.close()
        except Exception as e: #如果对方没有发送数据过来就执行下面的操作
            print (e)
            time.sleep(4) #相当于每隔4秒进行查看一次数据是否有发送过来
    
    ############################
    waiting client connection .......
    [WinError 10035] 无法立即完成一个非阻止性套接字操作。
    [WinError 10035] 无法立即完成一个非阻止性套接字操作。
    [WinError 10035] 无法立即完成一个非阻止性套接字操作。
    [WinError 10035] 无法立即完成一个非阻止性套接字操作。
    

     

    select模块

       select是IO多路复用的一种实现方式

      通过select模块来实现非阻塞IO,通过非多线程的方式实现多用户同时访问服务器

      select模块通过水平触发(只要有连接存在就触发)来检测server端是否有客户端连接server端

    import socket,select
    
    sk=socket.socket()
    sk.bind(("127.0.0.1",9904))
    sk.listen(5)
    inp=[sk,] #将server端的socket对象加入到列表中
    while True:
        #(input,output,errorput,time)
        r, w, e = select.select(inp, [], [], 5)  # select作为监听器(水平触发),来检测是有客户端来访问conn
                                                 # 每隔5秒钟执行一次查看,如果对方没有连接,那r为空值
        for i in r:#[sk,]
            # conn,add=i.accept() #这里没有进行客户端连接的操作,当循环退出后,再次监听,而r依然是存在sk的列表
            # print(conn)
            print("Hello")
        print('>>>>>>')
    
    #当一个客户端连接
    ################################
    >>>>>>
    Hello
    >>>>>>
    Hello
    >>>>>>
    Hello
    >>>>>>
    Hello
    .....

    server端实现多用户连接

    import socket,select
    
    sk=socket.socket()
    sk.bind(("127.0.0.1",9904))
    sk.listen(5)
    inp=[sk,]
    while True:
    
        r,w,e=select.select(inp,[],[],5) #[sk,conn]
    
        for i in r:#[sk,]
            conn,add=i.accept()
            print(conn)
            print("hello")
            inp.append(conn) #在监听列表中添加连接
            
        print('>>>>>>')
    
    import socket
    import select
    sk=socket.socket()
    sk.bind(("127.0.0.1",8801))
    sk.listen(5)
    inputs=[sk,]
    while True:
        r,w,e=select.select(inputs,[],[],5)
    
        for obj in r:#[sk,]
            if obj==sk:
                conn,add=obj.accept()
                print(conn)
                inputs.append(conn)
            else:
                data_byte=obj.recv(1024)
                print(str(data_byte,'utf8'))
                inp=input('回答%s号客户>>>'%inputs.index(obj))
                obj.sendall(bytes(inp,'utf8'))
    
        print('>>',r)
    两端交流server端
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 8801))
    
    while True:
        inp = input(">>>>")
        sk.sendall(bytes(inp, "utf8"))
        data = sk.recv(1024)
        print(str(data, 'utf8'))
    两端交流客户端

    selectors模块

    server端  

    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) #绑定连接,如果coon连接有活动,就直接执行read方法
    
    def read(conn, mask):
        try:
            data = conn.recv(1000)  # Should be ready
            if not data:
                raise Exception
            print('echoing', repr(data), 'to', conn)
            conn.send(data)  # Hope it won't block
        except Exception as e:
            print('closing', conn)
            sel.unregister(conn)
            conn.close()
    
    sock = socket.socket()
    sock.bind(('localhost', 8090))
    sock.listen(100)
    sock.setblocking(False)
    
    sel.register(sock, selectors.EVENT_READ, accept) #绑定连接,如果sock连接有活动,就直接执行accept方法
    print("server.....")
    
    while True:
        events = sel.select()#[sock,,conn2]
        for key, mask in events:
            callback = key.data
            callback(key.fileobj, mask)  

    服务端

    import socket
    
    sk=socket.socket()
    
    sk.connect(("127.0.0.1",8090))
    while 1:
        inp=input(">>>")
        sk.send(inp.encode("utf8"))
        data=sk.recv(1024)
        print(data.decode("utf8")
    
  • 相关阅读:
    React在componentDidMount里面发送请求
    React 术语词汇表
    React里受控与非受控组件
    React和Vue等框架什么时候操作DOM
    【LeetCode】79. Word Search
    【LeetCode】91. Decode Ways
    【LeetCode】80. Remove Duplicates from Sorted Array II (2 solutions)
    【LeetCode】1. Two Sum
    【LeetCode】141. Linked List Cycle (2 solutions)
    【LeetCode】120. Triangle (3 solutions)
  • 原文地址:https://www.cnblogs.com/shuzhixia/p/10835190.html
Copyright © 2011-2022 走看看