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")
    
  • 相关阅读:
    java基础
    HDOJ(HDU).2266 How Many Equations Can You Find (DFS)
    POJ.1416 Shredding Company (DFS)
    HDOJ(HDU).2044-2049 递推专题
    HDOJ(HDU).1045 Fire Net (DFS)
    HDOJ(HDU).1258 Sum It Up (DFS)
    HDOJ(HDU).1241 Oil Deposits(DFS)
    我的ACM参赛故事
    HDOJ(HDU).1035 Robot Motion (DFS)
    HDOJ(HDU).1016 Prime Ring Problem (DFS)
  • 原文地址:https://www.cnblogs.com/shuzhixia/p/10835190.html
Copyright © 2011-2022 走看看