Python之基于socket和select模块实现IO多路复用
'''IO指的是输入输出,一部分指的是文件操作,还有一部分
网络传输操作,例如soekct就是其中之一;多路复用指的是
利用一种机制,同时使用多个IO,例如同时监听多个文件句
柄(socket对象一旦传送或者接收信息),一旦文件句柄出
现变化就会立刻感知到
'''
1、下面通过IO多路复用实现多人同时连接socket服务器 这是服务端代码
import socket sk1 = socket.socket()#sk1,sk2,sk3这就是一个文件描述符
sk1.bind(('127.0.0.1',8002))
sk1.listen() sk2 = socket.socket()
sk2.bind(('127.0.0.1',8003))
sk2.listen() sk3 = socket.socket()
sk3.bind(('127.0.0.1',8004))
sk3.listen() inputs = [sk1,sk2,sk3]
import select
while True:
'''[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
一旦某个句柄发生变化就会被监听到
'''
#如果有人链接sk1,则会被添加进列表,r_list = [sk1]
r_list,w_list,e_list = select.select(inputs,[],[],1)#1表示等一秒,在while执行到这里的时候监测一秒,没有人来链接的话就接着循环
#print(r_list,sk1.listen())
for sk in r_list:
conn,address = sk.accept()
#print(conn,address)
conn.sendall(bytes('你好',encoding='utf-8'))
conn.close()
客户端的代码都是一样的,就差个端口
#客户端一
import socket obj = socket.socket()
obj.connect(('127.0.0.1',8002))
content = str(obj.recv(1024),encoding='utf-8')
print(content) obj.close() #客户端二
import socket obj = socket.socket()
obj.connect(('127.0.0.1',8003))
content = str(obj.recv(1024),encoding='utf-8')
print(content) obj.close() #客户端三
import socket obj = socket.socket()
obj.connect(('127.0.0.1',8004))
content = str(obj.recv(1024),encoding='utf-8')
print(content) obj.close()
执行结果:只要启动服务器端,然后不同的客户端多次启动都能收到信息,多个端口成功被监听
2、下面使用select模块实现多路复用,使同一个端口同时接收多个链接
import socket sk1 = socket.socket()#sk1,sk2,sk3这就是一个文件描述符
sk1.bind(('127.0.0.1',8002))
sk1.listen() #
# sk2 = socket.socket()
# sk2.bind(('127.0.0.1',8003))
# sk2.listen()
#
# sk3 = socket.socket()
# sk3.bind(('127.0.0.1',8004))
# sk3.listen() inputs = [sk1]
import select #epoll效率更高,但是Windows不支持,它是谁有问题就告诉它,不用循坏
while True:
'''[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
一旦某个句柄发生变化(某人来链接)就会被监听到
'''
#如果有人链接sk1,则会被添加进列表,r_list = [sk1]
r_list,w_list,e_list = select.select(inputs,[],[],1)
'''第三个参数是监听错误的,只要有错误出现,就会被监听到,返回e_list
第二个参数返回给w_list,只要传了什么,就原封不动的传给w_list'''
print('正在监听 %s 多少个对象' % len(inputs))
for sk in r_list:
if sk == sk1:
#句柄跟服务器端的对象一样,表示有新用户来链接了
conn,address = sk.accept()
inputs.append(conn)#加入去之后,inputs有一个链接对象和服务器对象
else:
#有老用户发消息了
try:
data_byte =sk.recv(1024) data_str =str(data_byte,encoding='utf-8')
sk.sendall(bytes(data_str+'收到了',encoding='utf-8'))
except:#空信息表示客户端断开链接,所以要在监听中移除 inputs.remove(sk)#这里的sk就是之前传进去的conn,因为r_list接收的是有变化的值
启动这个服务端之后,就可以实现多路复用了,可以接收多个客户端同时连接
3、下面介绍一些多路操作里面的读写分离
import socket sk1 = socket.socket()#sk1就是一个文件描述符
sk1.bind(('127.0.0.1',8002))
sk1.listen()
inputs = [sk1]#被检测发生变动的句柄放这里
outputs=[]#用来记录谁给服务端发过信息,以便回复
message_dict = {}#接收信息的,根据句柄形成键值对
import select #epoll效率更高,但是Windows不支持,它是谁有问题就告诉它,不用循坏
while True:
'''[sk1,sk2,sk3],select内部会自动监听sk1,sk21,sk3三个对象
一旦某个句柄发生变化(某人来链接)就会被监听到
'''
#如果有人链接sk1,则会被添加进列表,r_list = [sk1]
r_list,w_list,e_list = select.select(inputs,outputs,inputs,1)
'''第三个参数是监听错误的,只要有错误出现,就会被监听到,返回e_list
第二个参数返回给w_list,只要传了什么,就原封不动的传给w_list'''
print('正在监听 %s 多少个对象' % len(inputs))
for sk in r_list:
if sk == sk1:
#句柄跟服务器端的对象一样,表示有新用户来链接了
conn,address = sk.accept()
inputs.append(conn)#加入去之后,inputs有一个链接对象和服务器对象
message_dict[conn]=[]#字典的key是具体的链接对象
else:
#有老用户发消息了
try:
data_byte =sk.recv(1024) except Exception as e:#空信息表示客户端断开链接,所以要在监听中移除
print(e)
inputs.remove(sk)#这里的sk就是之前传进去的conn,因为r_list接收的是有变化的值
else:
data_str = str(data_byte, encoding='utf-8') message_dict[sk].append(data_str)
outputs.append(sk)#把传送数据的句柄添加进去第二个参数
for conn in w_list:
recv_str=message_dict[conn][0]#拿到我们收到了的信息
del message_dict[conn][0]#删除信息,防止下次出现一样的消息
print(recv_str)
conn.sendall(bytes(recv_str+'收到了',encoding='utf-8'))
outputs.remove(conn)#回复完成之后在列表删除
for sk_or_conn in e_list:
e_list.remove(sk_or_conn)
这样可以形成简单的读写分离操作
对于select里面的参数关系,这里有个武sir画的图

Python之基于socket和select模块实现IO多路复用的更多相关文章
- 在python中编写socket服务端模块(二):使用poll或epoll
在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...
- C#中级-从零打造基于Socket在线升级模块
一.前言 前段时间一直在折腾基于Socket的产品在线升级模块.之前我曾写过基于.Net Remoting的.基于WCF的在线升级功能,由于并发量较小及当时代码经验的不足一直没有实际应用. ...
- 【Socket】从零打造基于Socket在线升级模块
一.前言 前段时间一直在折腾基于Socket的产品在线升级模块.之前我曾写过基于.Net Remoting的.基于WCF的在线升级功能,由于并发量较小及当时代码经验的不足一直没有实际应用. ...
- select模块(I/O多路复用)
0709自我总结 select模块 一.介绍 Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持 ...
- Python进程、线程、协程及IO多路复用
详情戳击下方链接 Python之进程.线程.协程 python之IO多路复用
- python笔记8 socket(TCP) subprocess模块 粘包现象 struct模块 基于UDP的套接字协议
socket 基于tcp协议socket 服务端 import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 买 ...
- Python编写基于socket的非阻塞多人聊天室程序(单线程&多线程)
前置知识:socket非阻塞函数(socket.setblocking(False)),简单多线程编程 代码示例: 1. 单线程非阻塞版本: 服务端: #!/usr/bin/env python # ...
- Python练习-基于socket的FTPServer
# 编辑者:闫龙 import socket,json,struct class MySocket: with open("FtpServiceConfig","r&qu ...
- python selectors模块实现 IO多路复用机制的上传下载
import selectorsimport socketimport os,time BASE_DIR = os.path.dirname(os.path.abspath(__file__))''' ...
随机推荐
- HDU 1712 ACboy needs your help AC男需要你的帮助 (分组的背包)
分组背包问题:有N件物品和一个容量为V的背包.第i件物品的体积是c[i],价值是w[i].这些物品被划分为若干组,每组中的物品互相冲突,最多选一件.求解将哪些物品装入背包可使这些物品的体积总和不超过背 ...
- IOS autosizing(设置控件的固定位置大小)
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- ZOJ-1654 Place the Robots---二分图最小点覆盖+构图
题目链接: https://vjudge.net/problem/ZOJ-1654 题目大意: 有一个N*M(N,M<=50)的棋盘,棋盘的每一格是三种类型之一:空地.草地.墙.机器人只能放在空 ...
- 【BZOJ3925】[ZJOI2015] 地震后的幻想乡(状压期望DP)
点此看题面 大致题意: 有\(n\)个点和\(m\)条边,每条边的权值是一个\(0\sim1\)的随机实数,要你用\(n-1\)条边将图联通,问这\(n-1\)条边中边权最大值的期望最小值. 提示 这 ...
- 复习C++_基础、函数、数组、字符串
程序的开发过程 程序 源程序:用源语言写的,有待翻译的程序: 目标程序:源程序通过翻译程序加工以后生成的机器语言程序: 可执行程序:连接目标程序以及库中的某些文件,生成的一个可执行文件,例如Windo ...
- javaweb基础(25)_jsp标签实例一
一.简单标签(SimpleTag) 由于传统标签使用三个标签接口来完成不同的功能,显得过于繁琐,不利于标签技术的推广, SUN公司为降低标签技术的学习难度,在JSP 2.0中定义了一个更为简单.便于编 ...
- V8引擎——详解
前言 JavaScript绝对是最火的编程语言之一,一直具有很大的用户群,随着在服务端的使用(NodeJs),更是爆发了极强的生命力.编程语言分为编译型语言和解释型语言两类,编译型语言在执行之前要先进 ...
- lrzsz包中的rz和sz命令
安装包:lrzsz rz命令:将物理机文件复制到虚拟机 sz命令:将虚拟机文件复制到物理机
- win7在某个盘或文件夹中出现右键只能新建文件夹的情况 (2012-12-28-bd 写的日志迁移
至于只能新建文件夹的情况如图: 解决方法是在运行中输入msconfig进入如图: 在系统设置选工具项在选中更改UAC设置点击启动如图: 如图: 直接把通知栏拉到最低确定即可(如果已经是最低了那就随便改 ...
- Python9-IO模型-day41
# 进程:启动多个进程,进程之间是由操作系统负责调用# 线程:启动多个线程,真正由被cpu执行的最小单位实际是线程# 开启一个线程,创建一个线程,寄存器.堆栈# 关闭一个线程# 协程# 本质上是一个线 ...