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. web页面在微信里打开,字体颜色不正常显示

    问题:写的web项目在微信里的webview里打开(iphone手机),会出现颜色的不识别.写的是白色,数字的部分会过了3-5秒后,变成黑色! 原因:在iphone手机里,数字的部分(具体的长度没有测 ...

  2. __import__简介

    __import__()     import 语句通过调用__import__()来完成工作,提供这个函数是为了让有特殊需要的用户覆盖他,实现自定义.__import__最大的好处就是可以使程序在r ...

  3. xtrabackup在线备份主库,搭建slave,使用gtid模式

    mysql:5.6.29xtrabackup:2.2.10master:192.168.166.129slave:192.168.166.131mysql数据目录:/data/mysqlmysql备份 ...

  4. 微信小程序前置课程:Flex 布局教程(一):语法篇

    原文:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?utm_source=tuicool 网页布局(layout)是CSS的一个重点 ...

  5. Leetcode-34-Search for a Range-(Medium)

    这道题借助二分查找算法来查找目标值的index 然后向前和向后分别搜索起始边界 注意开始排除异常值优化速度 #!/usr/local/bin/python3 # -*- coding: utf-8 - ...

  6. js格式化时间为JSON格式 ajax提交 后台处理

    var effectRow = new Object();if ($('#grd_infos').datagrid('getChanges').length) {    var update = $( ...

  7. shell 脚本中for循环

    昨天很痛苦的搞了一天的for循环,在服务器上运行没啥问题,在设备上运行总是不行,部分代码如下: for(i=1;i<$cnt+1;i++)do echo "xxxx"  &g ...

  8. owa_outlook暴力破解脚本

    其实msf里面存在这样的模块,search owa 即可,字典这种东西还是找规律密码去破解比较好 然后担心遇到渗透测试没有msf情况下,还是得自己写个脚本,网上找了一下lijiejie,但是运行不了, ...

  9. VMware虚拟机服务的vmware-hostd自动启动和停止

    安装了虚拟机 任务管理器会出现vmware-hostd.exe  占用了80端口,导致xampp打不开,所以就想关闭vmware,解决方案如下: 开始——运行——services.msc,找到VM打头 ...

  10. 《Intel汇编第5版》 汇编逆转字符串

    一.逆转字符串 逆转一个字符串可以利用栈这个数据结果,顺次读取所有元素压栈,再出栈所有元素即可逆序 二.push和pop指令 三.pushfd和popfd 四.pushad和popad 五.代码以及结 ...