• python第10天(下)


    https://www.cnblogs.com/zingp/p/6863170.html 

    一:IO模型介绍

    IO发生时涉及的对象和步骤

      对于一个网络IO(network IO),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另一个就是系统内核(kernel)

      当一个read操作发生时,该操作会经历两个阶段:

       1)等待数据准备 (Waiting for the data to be ready)

      2)将数据从内核拷贝到进程中(Copying the data from the kernel to the process) 

      记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况

     

     1  1 import socket
     2  2 server=socket.socket()
     3  3 server.bind(("localhost",6969))
     4  4 server.listen()
     5  5 print("等待用户链接")
     6  6 while True:
     7  7     conn,addr=server.accept()
     8  8     while True:
     9  9         conn.send(("%s have connected to server"%addr).encode())
    10 10         data=conn.recv(1024)
    11 11         print("from client",data.decode())
    12 12 
    13 13 
    14 14 import socket
    15 15 client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    16 16 client.connect(("localhost",6969))
    17 17 while True:
    18 18     data=client.recv(1024)
    19 19     print("from server:",data.decode())
    20 20     client.send("hellow".encode())
    阻塞IO

     1 import socket,time
     2 server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
     3 server.bind(("localhost",6969))
     4 server.listen()
     5 server.setblocking(False)#设置为非阻塞,默认为阻塞
     6 print("等待用户链接")
     7 while True:
     8     try:
     9         conn,addr=server.accept()
    10         conn.send("you have connected to server".encode())
    11         data=conn.recv(1024)
    12         print("from client",data.decode())
    13         conn.close()
    14     except Exception as e:
    15         print(e)
    16         time.sleep(4)
    17 ##########
    18 import socket,time
    19 client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    20 while True:
    21     client.connect(("localhost", 6969))
    22     data=client.recv(1024)
    23     print("from server:",data.decode())
    24     client.send("hellow".encode())
    25     time.sleep(2)
    26     break
    非阻塞IO

    由于设置了非阻塞IO(setblocking())所以在accept()的时候会报错,因为抓住了错误,所以开始会输出错误信息 ,有个问题就是服务端接收不到了客户端的数据

    IO multiplexing:包括select,epoll,有些地方也称这种IO方式为event driven IO

    注意1:select函数返回结果中如果有文件可读了,那么进程就可以通过调用accept()或recv()来让kernel将位于内核中准备到的数据copy到用户区

    一:流程

    二:IO多路复用的触发方式

    • 水平触发
    • 边缘触发

    三:select实例

     1 import socket
     2 import select
     3 server=socket.socket()
     4 server.bind(("localhost",6969))
     5 server.listen()
     6 while True:
     7     r,w,e=select.select([server,],[],[],5)
     8     #rlist -- wait until ready for reading
     9     #wlist -- wait until ready for writing
    10     #xlist -- wait for an ``exceptional condition''
    11     #阻塞等待链接的时间
    12     for i in r:
    13         print(r)
    14         conn,addr=i.accept()
    15         print(conn)
    16         print(addr)
    17         print("hellow")
    18     print(">>>>>")
    19 ####################
    20 
    21 import socket,time
    22 client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    23 while True:
    24     client.connect(("localhost", 6969))
    25     print(client)
    26     data=client.recv(1024)
    27     print("from server:",data.decode())
    28     client.send("hellow".encode())
    select实现IO多路复用

    在不调用accept的时候,会反复的输出hellow和>是因为select的触发方式为水平触发

     1 import select,socket
     2 server=socket.socket()
     3 server.bind(("localhost",6969))
     4 server.listen(5)
     5 inp=[server,]
     6 while True:
     7     r, w, e = select.select(inp, [], [])
     8     for obj in r:
     9         if obj == server:
    10             print("r:", r)
    11             print(len(r))
    12             print(obj)
    13             conn, addr = obj.accept()
    14             inp.append(conn)
    15         else:
    16             print("obj:",obj)
    17             data=obj.recv(1024).decode()
    18             print(">>:",data)
    19             data=input("回答%s:"%str(addr))
    20             obj.send(data.encode())
    21 ###################################
    22 import socket
    23 client=socket.socket()
    24 client.connect(("localhost",6969))
    25 print(client)
    26 while True:
    27     inp=input(">>>>:")
    28     client.send(inp.encode())
    29     data=client.recv(1024).decode()
    30     print(data)
    select实现监听多链接

     

    异步IO全程无阻塞

     1 import selectors
     2 import socket
     3 def accept(server,mask):
     4     conn,addr=server.accept()
     5     print("client_sock:%s
    client_addr:%s"%(conn,addr))
     6     sel.register(conn,selectors.EVENT_READ,read)#注册,将conn和read函数绑定
     7 def read(conn,mask):
     8     try:#window如果客户端断开链接会报错,但是如果是linux客户端断开会发空数据,检测断开手段不一样
     9         data=conn.recv(1024)
    10         print(data.decode())
    11         conn.send(data)
    12     except Exception as e:
    13         print("close:%s"%conn)
    14         sel.unregister(conn)#解除绑定
    15         conn.close()
    16 if __name__ == '__main__':
    17 
    18     sel=selectors.DefaultSelector()#生成一个selector的对象
    19     print("sel:",sel)
    20     server=socket.socket()
    21     server.bind(("localhost",6969))
    22     server.listen()
    23     sel.register(server,selectors.EVENT_READ,accept)#注册,将server与accept绑定
    24     while True:
    25         events=sel.select()#相当于select.select()#检测是否有链接或已连接的socket是否发送数据
    26         print("events:",events)
    27         print("
    ")
    28         for key,mask in events:
    29             print("key:",type(key),key)#(SelectorKey(fileobj=<socket.socket fd=536, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 6969)>, fd=536, events=1, data=<function accept at 0x02C14E40>)
    30             callback=key.data
    31             callback(key.fileobj,mask)#调用相应的函数
    selctor实现IO多路复用
    
    
    
  • 相关阅读:
    docker-排除故障
    python的标识符
    python的数据类型
    python的数与字符串
    场景法
    正交试验法
    错误推测法
    决策表法
    因果图法
    python基础--用python执行系统命令
  • 原文地址:https://www.cnblogs.com/Mr-l/p/10426163.html
Copyright © 2020-2023  润新知