python IO模型和多路复用客户端服务端

news/2024/7/9 16:48:58 标签: python, epoll, 操作系统

IO 涉及到的对象和步骤

python">#
# # 前提需知道:操作系统的内核态和用户态 ,通信将数据缓存到内核,然后操作系统执行accept到用户态
#
# # IO发生时涉及的对象:
# # 对于一个network IO (这里我们以read举例),它会涉及到两个系统对象:
# # 一个是调用这个IO的进程或者线程
# # 另一个就是系统内核(kernel)
# #
# #
# # IO发生时涉及的步骤:
# # 当一个read操作发生时,它会经历两个阶段:
# #  1 等待数据准备 (Waiting for the data to be ready)
# #  2 将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)
# # 记住这两点很重要,因为这些IO Model的区别就是在两个阶段上各有不同的情况。
# # 在linux中,默认情况下所有的socket都是blocking,即阻塞IO。
#

  

1、blocking IO (阻塞IO):

python">#
#     当用户进程调用了recvfrom这个系统调用,内核kernel就开始了IO的第一个阶段:准备数据。
#     对于network io来说,很多时候数据在一开始还没有到达(比如,还没有收到一个完整的UDP包),
#     这个时候kernel就要等待足够的数据到来。而在用户进程这边,整个进程会被阻塞。
#
#     当内核kernel一直等到数据准备好了,它就会将数据从kernel中拷贝到用户内存,然后kernel返回结果,
#     用户进程才解除block的状态,重新运行起来。
#     所以,blocking IO的特点就是在IO执行的两个阶段都被block了。
#
#     简单总结:数据没来,一直等,没数据,复制也不行,一直等
#

  

2、non-blocking IO(非阻塞IO)

python"># linux下,可以通过设置socket使其变为non-blocking。
#
#     当用户进程发出read操作时,如果kernel中的数据还没有准备好,那么它并不会block用户进程,而是立刻返回一个error。
#     用户进程判断结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。
#     所以,用户进程其实是需要不断的主动询问kernel数据好了没有。进程在返回之后,可以干点别的事情,然后继续轮询。
#     注意,复制数据阶段仍然处于阻塞阶段。
#
#

  

3、IO multiplexing(IO多路复用)

python">#     IO multiplexing这个词可能有点陌生,但是如果我说select,epoll,大概就都能明白了。
#     有些地方也称这种IO方式为event driven IO。我们都知道,
#     select/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。
#     它的基本原理就是select/epoll这个function会不断的轮询所负责的所有socket,
#     当某个socket有数据到达了,就通知用户进程
#
#     当用户进程调用了select,那么整个进程会被block,而同时,kernel会“监视”所有select负责的socket,
#     当任何一个socket中的数据准备好了,select就会返回。
#     这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
#
# 用select的优势在于它可以同时处理多个connection。
# 所以,如果处理的连接数不是很高的话,使用select/epoll的web server不一定
# 比使用multi-threading + blocking IO的web server性能更好,可能延迟还更大。
# select/epoll的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。
#
#
# 注意1:select函数返回结果中如果有文件可读了,那么进程就可以通过调用accept()或recv()
# 来让kernel将位于内核中准备到的数据copy到用户区。
#
# 注意2: select的优势在于可以处理多个连接,不适用于单个连接

  

4、AsynchronousI / O(异步IO):

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

 

5、综合

python"># # 阻塞IO:等数据,数据不来,不走,全程阻塞
# # 一次accept,全程阻塞
#
#
# # 非阻塞io:问你有没有数据,有带着数据走,没有,带着错误走
# # socket.socket().setblocking(False)
# # 缺点:发多次系统调用,拿到的数据不一定是实时的
# # 优点:等待数据时无阻塞
# # 两个阶段:
# # 等待数据非阻塞
# # 复制数据阻塞
#
#
#
# # IO多路复用:(重点)
# # conn没有新链接监听
# # select监听有变化的套接字,有新链接
# # select监听数据,数据到了告诉他,不到就阻塞
#
# # 套接字对象(文件描述符):
# # 是一个非零整数,不会变
# # 收发数据的时候,对于接收端而言,数据先到内核空间,然后 copy
# # 到用户空间,同时,内核空间数据清除。
#
# # 2次调用,全程阻塞,select一次,accept一次
# # 特点:
# # 1全程阻塞(wait for data,copy)
# # 2能监听多个文件描述符
# # 3实现并发
#
# # 异步IO:
# # linux 下用的很少,实现复杂,用的少
#
# # 有一个阻塞就是同步,
# # 同步:阻塞io,非阻塞io,io多路复用
# # 异步:异步io

  

IO多路复用的客户端和服务器端

# IO多路复用client 端

import socket

sock=socket.socket()
sock.connect(("127.0.0.1",8888))

while 1:
    msg=input(">>:")
    sock.send(msg.encode("utf8"))
    data=sock.recv(1024)
    print(data.decode("utf8"))

sock.close()
# IO多路复用server 端

import socket

import select
sock=socket.socket()
sock.bind(("127.0.0.1",8888))

sock.listen(5)

sock.setblocking(False)
inputs=[sock,]

while 1:

    r,w,e=select.select(inputs,[],[])

    for obj in r:
        if obj == sock:
            conn,addr=obj.accept()
            print("conn",conn)
            inputs.append(conn)
        else:
            data = obj.recv(1024)
            print(data.decode("utf8"))

            msg=input(">>>:")
            obj.send(msg.encode("utf8"))

 

转载于:https://www.cnblogs.com/adamans/articles/7568813.html


http://www.niftyadmin.cn/n/1747380.html

相关文章

linux中pci设备和udev关系,udev研究之与模块关系

最近在做CLFS,又遇到了Udev的问题.自己对udev和模块之间加载和被加载,依靠和被依靠的关系一直有点不清楚,这次遇到了就索性搞明白.作者: Manson.Li更新日期:2007-9-12联系方式: lizhilianglove163.com转载请注明作者和出处.本文主要解决的问题是:1. udev创建设备文件需要事…

chrome自动填表会遮挡input中背景图的问题解决方法

在做某项目登录界面时,发现用户密码框在Chrome自动填充时,input中的背景框会被遮住。网上也搜了一下,没有一个有效的解决方法。 来看csdn的登录界面,也有这个问题。 后来在浏览网页时,无意中发现某网站的登录页面没有这…

linux fprintf %s 乱码,fprintf、fscanf读写乱码的问题

前几天写类linux文件系统的时候,被这个搞死了,今天终于弄懂了这是cpp文件#include #include #include #include using namespace std;char ch[250];struct s{short a, b;};int main(){FILE *file fopen("test.txt", "wt");s st;st.…

linux下显示以什么为脚本到行,一篇关于Linux下Shell脚本(Z)的阅读笔记

今天下了个名叫Z的压缩工具前端代码(版本2.7.1),读了下最大的感觉就是要学的东西还有好多呀~~~这篇blog里记录了我是我阅读源码后总结的几个知识点OSC上Z的页面地址:http://www.oschina.net/p/zZ的官方地址:http://www.cs.indiana.edu/~kinzl…

day07面向对象+

面向对象(构造方法Constructor概述和格式)面向对象(构造方法的重载及注意事项)面向对象(给成员变量赋值的两种方式的区别)面向对象(学生类的代码及测试)面向对象(手机类的代码及测试)面向对象(创建一个对象的步骤)面向对象(长方形案例练习)面向对象(员工类案例练习)面向对象(st…

Linux破坏系统的代码,Linux文件系统被破坏时的处理方法介绍

Linux文件系统被破坏时的处理方法介绍当文件系统被破坏时,如果使用的是ext2fs类型的文件系统,就可从软盘运行e2fsck命令来修正文件系统中被损坏的数据。对于其他类型的文件系统,可以使用相应的fsck命令。当从软盘上检查文件系统时&#xff0c…

Docker和LXC有什么不同?

本文讲的是Docker和LXC有什么不同?,【编者的话】Docker和LXC有什么不同?这大概是很多初学者的困惑所在,为什么说Docker不是LXC的一个替代方案呢? Docker基于LXC的基础上做了哪些有想象力的工作呢? 本文作者就此分享了自己的一些独特见解。 自Docker诞…

ThinkPHP函数详解:L方法

L方法用于启用多语言的情况下,设置和获取当前的语言定义。调用格式:L(语言变量[,语言值])设置语言变量除了使用语言包定义语言变量之外,我们可以用L方法动态设置语言变量,例如: L(LANG_VAR,语言定义);复制代码语言定义…