IO多路复用select模块加socket模块,伪多线并发,并不是真正的多线程并发,实际通过循环等待还是一个一个处理的

IO多路复用,lo就是文件或数据的输入输出,IO多路复用就是可以多用户操作

IO多路复用,可以监听多个文件描述符(socke对象)(文件句柄),一旦文件句柄出现变化,即可感知到,感知到后作出相应操作

比如原生socke模块只能监听一个端口和只能一个用户连接,要想实现监听多个端口和支持多用户,就会使用IO多路复用

IO多路复用select模块

select()自动监听socket对象的客户端,连接地址和、客户端通讯地址,四个参数

select()自动监听列表里的socket对象(文件描述符),一旦监听的对象,谁发生了变化(有用户请求),
就将发生变化对象的客户端连接地址赋值给第一个变量a,第一个变量接收的列表,列表里的每一个元素,就是一个端口的用户连接地址
如果是多个端口在同时连接客户端,那么列表元素就是多个元素

最多监听端口1024个

使用方法:a, b, c = select.select(列表类型的socke对象变化, [可选:传参直接赋值给第二个变量], [可选:列表类型的socke对象监听错误], 多少秒检测一次)

  需要四个参数 

  参数一:列表类型的socke对象,监听变化

  参数二:传参直接赋值给第二个变量

  参数三:列表类型的socke对象,监听错误

  参数四:多少秒检测一次

  需要三个变量来接收返回值

  第一个变量接收的:列表类型客户端连接地址,如果无客户端连接则为空列表

  第二个变量接收的:第二个参数的值

  第三个变量接收的:第三个参数监听socke对象的错误信息,返回列表,无错误则为空列表

格式:a, b, c = select.select(lib, [], [], 1)

格式2:a, b, c = select.select(lib, k1, lib, 1)

IO多路复用多端口监听客户端连接地址、服务端代码

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""服务端"""
import socket #导入模块
"""设置多个对象,绑定不同端口"""
k1 = socket.socket() #创建对象
k1.bind(('127.0.0.1', 9991)) #绑定服务端IP和端口
k1.listen() #监听IP和端口 k2 = socket.socket() #创建对象
k2.bind(('127.0.0.1', 9992)) #绑定服务端IP和端口
k2.listen() #监听IP和端口 k3 = socket.socket() #创建对象
k3.bind(('127.0.0.1', 9993)) #绑定服务端IP和端口
k3.listen() #监听IP和端口
"""将多个对象组合成列表"""
lib = [k1, k2, k3] """使用自动监听模块"""
import select #导入自动监听多个端口模块
while True:
#select()自动监听列表里的socket对象(文件描述符),一旦监听的对象,谁发生了变化(有用户请求),
# 就将发生变化对象的客户端连接地址赋值给第一个变量a,第一个变量接收的列表,列表里的每一个元素,就是一个端口的用户连接地址
#如果是多个端口在同时连接客户端,那么列表元素就是多个元素
a, b, c = select.select(lib, [], [], 1)
for k in a: #循环出select()获取到的列表类型客户端连接地址
d, e = k.accept() #将循环到的每一个客户端连接地址等待通讯,阻塞
d.sendall(bytes("欢迎访问", encoding="utf-8")) #向连接的客户端发送一条消息

客户端代码1

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""创建客户端"""
import socket #导入模块
z = socket.socket() #创建socket对象
b = z.connect(('127.0.0.1', 9991,))#连接服务端,在客户端绑定服务端IP和端口 f = z.recv(1024) #客户端接收服务端sendall()发来的信息,1024表示最大接收1024字节
f2 = str(f, encoding='utf-8') #将接收到的服务端字节信息转换成字符串
print(f2) #打印出服务端发来的信息

客户端代码2

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""创建客户端"""
import socket #导入模块
z = socket.socket() #创建socket对象
b = z.connect(('127.0.0.1', 9992,))#连接服务端,在客户端绑定服务端IP和端口 f = z.recv(1024) #客户端接收服务端sendall()发来的信息,1024表示最大接收1024字节
f2 = str(f, encoding='utf-8') #将接收到的服务端字节信息转换成字符串
print(f2) #打印出服务端发来的信息

IO多路复用多端口监听、客户端连接地址原理图

IO多路复用监听客户端多通讯地址

通过select()监听到客户端变化信息对象,拿到变化信息对象,判断是连接信息对象,还是通讯信息对象?如果是连接信息对象,通过变化信息对象获取到此连接的通讯对象,将通讯对象添加到select()里监听,如果是通讯对象,通过通讯对象进行信息交互

IO多路复用监听客户端多通讯地址服务端代码

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""服务端"""
import socket #导入模块
k1 = socket.socket() #创建对象
k1.bind(('127.0.0.1', 9991)) #绑定服务端IP和端口
k1.listen() #监听IP和端口
lib = [k1] """使用自动监听模块"""
import select #导入自动监听多个端口模块
while True:
#select()自动监听列表里的socket对象(文件描述符),一旦监听的对象,谁发生了变化(有用户请求),
# 就将发生变化对象的客户端连接地址赋值给第一个变量a,第一个变量接收的列表,列表里的每一个元素,就是一个端口的用户连接地址
#如果是多个端口在同时连接客户端,那么列表元素就是多个元素
a, b, c = select.select(lib, [], [], 1)
print("正在监听的socket对象 %d" % len(lib)) #监听的对象有多少个
print(a) #监听发生变化的有哪些
for k in a: #循环出select()获取到的列表类型客户端连接地址
if k == k1: #判断循环到的连接地址等于socket对象,说明有新用户连接
d, e = k.accept() #等待请求,获取客户端通讯地址
lib.append(d) #将客户端通讯地址追加到列表,传入select()监听通讯变化
d.sendall(bytes("你好", encoding="utf-8"))
else: #如果不是连接信息,说明是通讯信息
try: #监控代码是否出现异常,如果客户端关闭了就会出现异常,没出现异常执行里面的代码
fd = k.recv(1024)
f = str(fd, encoding="utf-8")
g = f + "好"
k.sendall(bytes(g, encoding="utf-8"))
except Exception as ex: #出现异常将当前通讯对象移除列表,select不在监听
lib.remove(k)

客户端代码

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""创建客户端"""
import socket #导入模块
z = socket.socket() #创建socket对象
b = z.connect(('127.0.0.1', 9991,))#连接服务端,在客户端绑定服务端IP和端口
while True:
f = z.recv(1024) #客户端接收服务端sendall()发来的信息,1024表示最大接收1024字节
f2 = str(f, encoding='utf-8') #将接收到的服务端字节信息转换成字符串
print(f2) #打印出服务端发来的信息
a = input("输入要发送的信息")
z.sendall(bytes(a, encoding="utf-8"))

IO多路复用监听客户端多通讯原理图

IO多路复用,有三种方式(select)、(poll)、(epoll) select和poll其实都是调用计算机底层来实现的监听处理,epoll是异步处理的是文件描述符发生变化后主动告诉epoll的,这里我们需要知道一下

注意:wds系统只支持select模块,

利用select()的第二个参数,实现IO多路复用,服务端读写分离
也就是读和写分开,在不同的代码块

服务端读写分离代码

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""服务端实现读写分离"""
import socket #导入模块
k1 = socket.socket() #创建对象
k1.bind(('127.0.0.1', 9991)) #绑定服务端IP和端口
k1.listen() #监听IP和端口 lib = [k1] #监听的客户连接地址或,客户通讯地址,传给select第一个参数
lib2 = [] #接收客户端通讯地址,传给select第二个参数
jilu = {} #接收字典,里面是客户端发通讯内容的用户通讯地址(键)和通讯内容(值) """使用自动监听模块"""
import select #导入自动监听多个端口模块
while True:
#select()自动监听列表里的socket对象(文件描述符),一旦监听的对象,谁发生了变化(有用户请求),
# 就将发生变化对象的客户端连接地址赋值给第一个变量a,第一个变量接收的列表,列表里的每一个元素,就是一个端口的用户连接地址
#如果是多个端口在同时连接客户端,那么列表元素就是多个元素
a, b, c = select.select(lib, lib2, lib, 1)
print("正在监听的socket对象 %d" % len(lib)) #监听的对象有多少个
print(a) #监听发生变化的有哪些
"""循环判断链接地址或通讯地址,获取客户端通讯信息以及内容"""
for k in a: #循环出select()获取到的列表类型客户端连接地址
if k == k1: #判断循环到的连接地址等于socket对象,说明有新用户连接
d, e = k.accept() #等待请求,获取客户端通讯地址
lib.append(d) #将客户端通讯地址追加到列表,传入select()监听通讯变化
jilu[d] = [] #将连接用户通讯地址添加到字典为键,值为空列表
else: #如果不是连接信息,说明是通讯信息
try: #监控代码是否异常
fd = k.recv(1024) #获取客户端发的信息
except Exception as e: #如果异常将此通讯地址移除列表,停止监听
lib.remove(k) #通讯地址移除列表
else:
fd2 = str(fd, encoding="utf-8") #接收客户端发的信息转换成字符串
jilu[k].append(fd2) # 将客户端转换的字符串追加到,字典里当前客户键的,列表里为值
lib2.append(k) #将当前客户通讯地址,添加到select第二个参数列表里
"""向客户端发信息"""
for km in b: #循环select第二个参数列表里的通讯用户
jkd = jilu[km][0] #通过通讯用户拿到字典里对应的通讯内容
del jilu[km][0] #拿到通讯内容后删除通讯内容
km.sendall(bytes(jkd+"好", encoding="utf-8")) #将通讯内容加个好字,在发给客户端
lib2.remove(km ) #在通讯列表移除当前通讯地址 for fh in c: #如果监听连接出现异常
lib.remove(fh) #移除当前连接

客户端代码

#!/usr/bin/env python
# -*- coding:utf8 -*-
"""创建客户端"""
import socket #导入模块
z = socket.socket() #创建socket对象
b = z.connect(('127.0.0.1', 9991,))#连接服务端,在客户端绑定服务端IP和端口
while True:
a = input("输入要发送的信息")
z.sendall(bytes(a, encoding="utf-8"))
f = z.recv(1024) #客户端接收服务端sendall()发来的信息,1024表示最大接收1024字节
f2 = str(f, encoding='utf-8') #将接收到的服务端字节信息转换成字符串
print(f2) #打印出服务端发来的信息

IO多路复用,服务端读写分离原理图

第五十五节,IO多路复用select模块加socket模块,伪多线并发的更多相关文章

  1. 第三百五十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—数据收集(Stats Collection)

    第三百五十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—数据收集(Stats Collection) Scrapy提供了方便的收集数据的机制.数据以key/value方式存储,值大多是计数 ...

  2. 第三百五十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)介绍以及安装

    第三百五十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)介绍以及安装 elasticsearch(搜索引擎)介绍 ElasticSearch是一个基于 ...

  3. 第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点

    第三百五十六节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy分布式爬虫要点 1.分布式爬虫原理 2.分布式爬虫优点 3.分布式爬虫需要解决的问题

  4. 第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解

    第三百五十五节,Python分布式爬虫打造搜索引擎Scrapy精讲—scrapy信号详解 信号一般使用信号分发器dispatcher.connect(),来设置信号,和信号触发函数,当捕获到信号时执行 ...

  5. 第三百五十五天 how can I 坚持

    快一年了,三百五十五天了,等写个程序算算时间,看看日期和天数能不能对的上,哈哈. 计划还是未制定,天气预报还是没有写完,立马行动,发完这个博客,立马行动. 计划:设计模式1个月,三大框架3个月,计算机 ...

  6. Linux IO多路复用 select

    Linux IO多路复用 select 之前曾经写过简单的服务器,服务器是用多线程阻塞,客户端每一帧是用非阻塞实现的 后来发现select可以用来多路IO复用,就是说可以把服务器这么多线程放在一个线程 ...

  7. “全栈2019”Java第五十五章:方法的静态绑定与动态绑定

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. io多路复用-select()

    参照<Unix网络编程>相关章节内容,实现了一个简单的单线程IO多路复用服务器与客户端. 普通迭代服务器,由于执行recvfrom则会发生阻塞,直到客户端发送数据并正确接收后才能够返回,一 ...

  9. 孤荷凌寒自学python第五十五天初识MongoDb数据库

    孤荷凌寒自学python第五十五天第一天初识MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 大家好,2019年新年快乐! 本来我想的是借新年第一天开始,正式尝试学习爬虫,结果今天偶然发现 ...

随机推荐

  1. Python print报ascii编码异常的靠谱解决办法

    之前遇到此异常UnicodeEncodeError: 'ascii' codec can't encode characters...,都是用这种方式解决:sys.setdefaultencoding ...

  2. (八)python的简单数据类型和变量

    什么是数据类型? 程序的本质就是驱使计算机去处理各种状态的变化,这些状态分为很多种. 例如英雄联盟游戏,一个人物角色有名字,钱,等级,装备等特性,大家第一时间会想到这么表示 名字:德玛西亚------ ...

  3. javascript:;”是什么意思

    就是 执行一段 空白JAVASCRIPT语句 并且返回的也是空或者false值..把 javascript:; 加在超级链接上 就可以防止 链接跳转..从而 可以给 链接的 onclick 方法上 写 ...

  4. 三分钟跑起jsblocks

      1下载代码 git clone https://github.com/astoilkov/jsblocks-seed.git 2安装依赖 Peng@PENG-PC /F/home/qianduan ...

  5. 校门外的树 OpenJudge 1.6.06

    06:校门外的树 总时间限制:  1000ms 内存限制:  65536kB 描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0 ...

  6. JavaEE XML SAX解析

    SAX解析XML @author ixenos SAX解析工具 SAX解析工具-  Sun公司提供的.内置在jdk中.org.xml.sax.* 核心的API: SAXParser类: 用于读取和解析 ...

  7. Girl Develop It Chapter Leaders at 2015 Annual Leadership Summit

    Girl Develop It Chapter Leaders at 2015 Annual Leadership Summit Corinne Warnshuis, Executive Direct ...

  8. Ubuntu 14.04 登陆界面循环问题解决

    今天手贱startx然后虚拟机就卡死了,再开输过密码就无限跳到登陆界面,其他账户可用.怀疑/home未挂载. 解决方法:(alf改成你的用户名) $ cd ~$ sudo chown alf:alf. ...

  9. Shell终端收听音乐--网易云音乐命令行版

    Musicbox:网易云音乐命令行版本 高品质网易云音乐命令行版本,简洁优雅,丝般顺滑,基于Python编写. 这款命令行的客户端使用 Python 构建,以 mpg123 作为播放后端: Vim 式 ...

  10. 安卓平台多个视频叠加演示demo说明

    多个音视频编辑演示说明: 第一个-----字幕和视频的叠加: 说明: 把字幕文件中的文字,按照时间叠加到视频上去,形成新的视频. 类似我们看电影时的字幕. 下载地址:http://www.cnblog ...