python自动化开发学习 I/O多路复用

 

一. 简介

  socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信。IO多路复用的系统消耗很小。

IO多路复用底层就是监听socket对象内部是否有变化,是否在收发消息,Python中select模块提供了select poll epoll 三种方式来实现IO多路复用,支持不同的操作系统。

  windows : 提供select

  Mac : 提供select

  Linux : 提供select, poll, epoll

(1)select简介:

  select 默认会将每一个变化的socket加入一个他自己维护的列表中,但是并不会明确是哪一个socket,它内部其实是通过一个for循环遍历整个列表,当列表中的socket很多的时候,for循环就会浪费资源。select默认可以监听1024个链接,它是由linux在同文件中定义的,可修改。select不是安全的线程,如果你把一个socket加入到select中,突然另外一个线程关闭了这个socket,那么接下来select的行为是随机的。

(2)poll简介:

  poll修复了select的一些问题,例如去掉了1024个链接限制,想要监听多少都可以,poll不在修改传入的数组,但是poll依然不是线程安全的。

(3)epoll简介:

  epoll不仅会告诉你socket组里面的数据,还会告诉你具体哪个socket有数据,无需自己寻找。而且epoll终于是线程安全的了。然而epoll局限于

Linux操作系统。

二 . 应用

select 方法

1
2
3
4
5
6
7
8
9
10
句柄列表11, 句柄列表22, 句柄列表33 = select.select(句柄序列1, 句柄序列2, 句柄序列3, 超时时间)<br>
参数: 可接受四个参数(前三个必须)
返回值:三个列表
   
select方法用来监视文件句柄,如果句柄发生变化,则获取该句柄。
1、当 参数1 序列中的句柄发生可读时(accetp和read),则获取发生变化的句柄并添加到 返回值1 序列中
2、当 参数2 序列中含有句柄时,则将该序列中所有的句柄添加到 返回值2 序列中
3、当 参数3 序列中的句柄发生错误时,则将该发生错误的句柄添加到 返回值3 序列中
4、当 超时时间 未设置,则select会一直阻塞,直到监听的句柄发生变化
   当 超时时间 = 1时,那么如果监听的句柄均无任何变化,则select会阻塞 1 秒,之后返回三个空列表,如果监听的句柄有变化,则直接执行。

(1)监听客户端连接

 服务端
import socket
import select
sk = socket.socket()
sk.bind(("127.0.0.1", 9999,))
sk.listen(5)
while True:
rlist, w, e = select.select([sk, ], [], [], 5)
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有消息发送过来了,此时rlist的值为[客户端]
print(rlist)
for r in rlist:
print(r)
conn, address = r.accept()
conn.sendall(bytes("hello", encoding="utf-8"))
服务端
 客户端
import socket
sk = socket.socket()
sk.connect(("127.0.0.1", 9999,))
data = sk.recv(1024)
print(data)
while True:
input(">>")
sk.close()
客户端

(2)监听客户端连接及接受客户端发送的数据

import socket
import select
sk = socket.socket()
sk.bind(("127.0.0.1", 9999,))
sk.listen(5) inputs = [sk,]
while True:
rlist, w, e = select.select(inputs, [], [], 1)
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有消息发送过来了,此时rlist的值为[客户端]
print(len(inputs), len(rlist))
for r in rlist:
print(r)
if r == sk:
# 有新的客户端连接进来
conn, address = r.accept()
inputs.append(conn)
conn.sendall(bytes("hello", encoding="utf-8"))
else:
# 有客户端给我发送数据
recv_data = r.recv(1024)
print(recv_data)
服务端
import socket
sk = socket.socket()
sk.connect(("127.0.0.1", 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input(">>")
sk.sendall(bytes(inp, encoding='utf-8'))
sk.close()
客户端

(3)读写分离

import socket
import select
sk = socket.socket()
sk.bind(("127.0.0.1", 9999,))
sk.listen(5) inputs = [sk,]
outputs = []
while True:
rlist, wlist, e = select.select(inputs, outputs, [], 1)
# 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为[sk]
# 监听conn对象,如果conn发生变化,表示客户端有消息发送过来了,此时rlist的值为[客户端]
print(len(inputs), len(rlist))
for r in rlist:
print(r)
if r == sk:
# 有新的客户端连接进来
conn, address = r.accept()
inputs.append(conn)
conn.sendall(bytes("hello", encoding="utf-8"))
else:
# 有客户端给我发送数据
try:
recv_data = r.recv(1024)
if not recv_data: # 某些操作系统,在socket断开的时候,会发送一个空给server,所以要判断空的情况
raise Exception("断开连接")
else:
outputs.append(r)
except Exception as e:
inputs.remove(r)
for w in wlist:
w.sendall(bytes("response", encoding="utf-8"))
outputs.remove(w)
服务端
import socket
sk = socket.socket()
sk.connect(("127.0.0.1", 9999,))
data = sk.recv(1024)
print(data)
while True:
inp = input(">>")
sk.sendall(bytes(inp, encoding='utf-8'))
print(sk.recv(1024))
sk.close()
客户端

(4)读写分离之服务端根据客户端的输入返回对应的信息

import socket
import select
sk = socket.socket()
sk.bind(("127.0.0.1", 9999,))
sk.listen(5) inputs = [sk, ] #
outputs = []
messages = {} # 用来存放客户端发送过来的消息,存放格式 连接客户端的对象: 消息
while True:
rlist, wlist, elist = select.select(inputs, outputs, [sk, ], 1)
# rlist 监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端来连接了,此时rlist值为[sk]
# wlist 监听conn对象,如果conn发生变化,表示客户端有消息发送过来了,此时rlist的值为[客户端]
# elist 监听sk(服务器端)对象是否发生错误
print(len(inputs), len(rlist))
for r in rlist:
print(r)
if r == sk:
# 有新的客户端连接进来
conn, address = r.accept()
inputs.append(conn)
messages[conn] = [] # 在存储消息的字典中创建一个以客户端连接对象为key 空列表为value的键值对
conn.sendall(bytes("hello", encoding="utf-8"))
else:
# 有客户端给我发送数据
try:
recv_data = r.recv(1024)
if not recv_data: # 某些操作系统,在socket断开的时候,会发送一个空给server,所以要判断空的情况
raise Exception("断开连接")
else:
outputs.append(r)
messages[r].append(recv_data)
except Exception as e:
inputs.remove(r)
del messages[r]
for w in wlist:
print(messages[w])
msg = messages[w].pop()
resp = msg + bytes("response", encoding="utf-8")
w.sendall(resp)
outputs.remove(w)
服务端

  

python自动化开发学习 I/O多路复用的更多相关文章

  1. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  2. Python自动化开发学习20-Django的form组件

    武沛齐老师的Django的FORM组件:http://www.cnblogs.com/wupeiqi/articles/6144178.html 转自:http://blog.51cto.com/st ...

  3. 《Python Web开发学习实录》高清PDF版|百度网盘免费下载|Python Web开发学习实录

    <Python Web开发学习实录>高清PDF版|百度网盘免费下载|Python Web开发学习实录 提取码:9w3o 内容简介 Python是目前流行的动态脚本语言之一. 李勇,本书共1 ...

  4. python web 开发学习路线

    转载,备着 自己目前学习python web 开发, 经过两个月的摸索,目前对web开发有了浅显的认识,把自己的学习过程贴出来.1.python入门推荐老齐<从零开始学python>,&l ...

  5. Selenium2+python自动化(学习笔记3)

    1.加载firefox配置 参考代码: # coding=utf-8from selenium import webdriver# 配置文件地址,打开Firefox点右上角设置--帮助--故障排除信息 ...

  6. Python自动化开发-简介

    1.Python简介 Python创始人  Guido Van Rossum,人称"龟叔",1989年圣诞节期间,为了在阿姆斯特丹打发时间,开发的一个新的脚本解释程序 作为ABC语 ...

  7. python自动化开发-1

    1.python简介 python是一门简明并且强大的面向对象的开发语言,已经在WEB开发,软件开发,科学计算,大数据分析,自动化运维等领域得到了广泛的应用. 注意:所有测试均已python3为主,与 ...

  8. 写给深圳首期Python自动化开发周未班的信

    你是否做了正确的决定? 深圳首期周未班的同学们大家好,我是Alex, 老男孩教育的联合创始人,Python项目的发起人,51CTO学院连续2届最受学员喜爱的讲师,中国最早一批使用Python的程序员, ...

  9. python自动化开发-[第九天]-异常处理、进程

    今日概要: 1.异常处理使用 2.进程 3.paramiko模块使用 一.异常处理 1.常见的错误异常 #错误异常一 print(a) #NameError #错误异常二 int('sdadsds') ...

随机推荐

  1. ActivityLifecycleCallbacks 如何控制activity的生命周期

    Android开发 - ActivityLifecycleCallbacks使用方法初探 初识 ActivityLifecycleCallbacks 利用ActivityLifecycleCallba ...

  2. php党 强烈推荐TIPI:深入理解PHP内核

    深入理解PHP内核(Thinking In PHP Internals) TIPI项目是一个自发项目, 项目主要关注PHP的内部实现, 以及PHP相关的方方面面, 该项目包括<深入理解PHP内核 ...

  3. Django开发之html交互

    html中用户输入信息,由Django的view.py处理,大致用到了以下几类格式: 1. 文本框 <input type="text" name="vid&quo ...

  4. iOS 动画基础总结篇

    iOS 动画基础总结篇   动画的大体分类(个人总结可能有误) 分类.png UIView 动画 属性动画 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1 ...

  5. SuperAgent使用文档

    SuperAgent是一个轻量级.灵活的.易读的.低学习曲线的客户端请求代理模块,使用在NodeJS环境中.官方文档:http://visionmedia.github.io/superagent 简 ...

  6. dubbo启动报错多个资源争缓存问题

    Dubbo Failed to save registry store file, cause: Can not lock the registry cache file 目录(?)[+] 启动的Du ...

  7. 【python】-- 文件操作

    一.概述 我们工作中需要经常操作文件,下面就讲讲如何用Python操作文件 1.文件操作的流程: 打开文件,得到文件句柄赋值给一个变量 通过文件句柄,对文件进行操作 关闭文件 #获取文件句柄 f = ...

  8. 我的Java开发学习之旅------>Java 格式化类(java.util.Formatter)基本用法

    本文参考: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html http://www.blogjava.net/ ...

  9. 聊聊数据库~6.SQL运维中篇

    上篇回顾:https://www.cnblogs.com/dotnetcrazy/p/10810798.html#top 1.6.5.MySQL日志相关 本文的测试环境:MySQL5.7.26.Mar ...

  10. PostgreSQL 里面的 BIGSERIAL

    @Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id; CREATE TABLE article( id BIGS ...