zoukankan      html  css  js  c++  java
  • Python IO模型

    这篇博客是本人借鉴一些大神的博客并结合自己的学习过程写下的。

    事件驱动模型

    事件驱动模型是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时,不断从队列里取出事件,根据不同的事件,调用不同的函数,然后通过使用回调机制来触发相应的处理。

    IO多路复用

    阻塞IO(blocking IO)

    当用户进程调用了recvfrom时,kernel就开始准备数据。在此期间对于network io来说,很多时候完整的数据在一开始还没有到达,这个时候kernel就要等待足够的数据到来。而在Process这边,整个进程便会被阻塞。当kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,用户进程才解除block的状态,重新运行起来。

    非阻塞IO(non-blocking IO)

    当用户进程向kernel发送数据请求时,如果数据还没有到kernel中,那么就会返回一个error。当用户进程收到error后,会不断地向kernel发送数据请求,直到最后拿到数据。在每一次recvfrom的时候,CPU的权限还在进程这里,那么CPU便可以干点其他事情。但是需要注意,拷贝数据整个过程,进程仍然是属于阻塞的状态。

     IO多路复用(IO multiplexing)

    select就是一种IO multiplexing,当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。IO multiplexing的优点在于能够同时处理多个connection,另外process的阻塞是被select这个函数block,而不是被socket IO给block。

    异步IO(Asynchronous IO)

    用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

    select模块实例

     1 ##############server##############
     2 import socket, select
     3 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     4 sk.bind(("192.168.43.159", 8001))
     5 sk.listen(5)
     6 inputs = [sk,]
     7 while True:
     8     r,w,e = select.select(inputs, [], [], 5) ##监听
     9     for obj in r:
    10         if obj == sk:
    11             conn,addr = obj.accept()
    12             print(conn)
    13             inputs.append(conn)
    14         else:
    15             try:
    16                 data = obj.recv(1024)
    17                 print(data.decode("UTF-8"))
    18                 inp = input("回答%s号客户:" %inputs.index(obj))
    19                 obj.sendall(inp.encode("utf-8"))
    20             except Exception:  ##防止连接断开
    21                 inputs.remove(obj)
    22                 
    23 ##############client##############
    24 import socket
    25 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    26 sk.connect_ex(("192.168.43.159", 8001))
    27 while True:
    28     answ = input(">>>")
    29     sk.send(answ.encode("utf8"))
    30     data = sk.recv(1024)
    31     print(data.decode("utf-8"))
  • 相关阅读:
    Swift
    UIWindow 详解及使用场景
    点击状态栏回到顶部的功能失效的解决办法
    iOS
    从经典问题来看 Copy 方法
    从汇编层面深度剖析C++虚函数
    数值的整数次方
    求整数二进制中1的个数
    C++中的位运算总结
    嵌入在C++程序中的extern "C"
  • 原文地址:https://www.cnblogs.com/MingleYuan/p/10588988.html
Copyright © 2011-2022 走看看