【Python】 select模块详解 所有程序猿必看!!!

要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值。
select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息

在网上一直在找这个select.select的参数解释, 但实在是没有, 哎…自己硬着头皮分析了一下。
readable, writable, exceptional = select.select(inputs, outputs, inputs)

select 函数的参数其实很好理解, 前提是我们对unix 网络编程有了解. select 模型是unix 系统中的网络模型, python 将其封装了,因此我们使用起来就比较方便, 但是面试官就不会这么觉得了(最近被面试逼疯了, 考虑问题都从面试官的角度考虑), 先说下unix 系统中的select 模型吧, 参数原型:
int select(int maxfdpl, fd_set * readset, fd_set *writeset, fd_set *exceptset, const struct timeval * tiomeout)

第一个是最大的文件描述符长度
第二个是监听的可读集合
第三个是监听的可写集合
第四个是监听的异常集合
第五个是时间限制

对struct fd_set结构体操作的宏
FD_SETSIZE 容量,指定fd_array数组大小,默认为64,也可自己修改宏
FD_ZERO(*set) 置空,使数组的元素值都为3435973836,元素个数为0.
FD_SET(s, *set) 添加,向 struct fd_set结构体添加套接字s
FD_ISSET(s, *set) 判断,判断s是否为 struct fd_set结构体中的一员
FD_CLR(s, *set) 删除,从 struct fd_set结构体中删除成员s

因为此模型主要是在网络中应用, 我们不考虑文件, 设备, 单从套接字来考虑, 可读条件如下:

可写条件如下:

我看C 示例的时候, 看的有点懵逼, 应该需要跑一遍代码就好, python 就简单了, 直接调用封装好的select , 其底层处理好了文件描述符的相关读写监听(回头再研究下), 我们在Python 中只需这么写:
can_read, can_write, _ = select.select(inputs, outputs, None, None)

第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字, 第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置.

如果监听的套接字满足了可读可写条件, 那么所返回的can,read 或是 can_write就会有值了, 然后我们就可以利用这些返回值进行随后的操作了。相比较unix 的select模型, 其select函数的返回值是一个整型, 用以判断是否执行成功.

第一个参数就是服务器端的socket, 第二个是我们在运行过程中存储的客户端的socket, 第三个存储错误信息。
重点是在返回值, 第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的
list。
网上所有关于select.select的代码都是差不多的, 但是有些不能运行, 或是不全。我自己重新写了一份能运行的程序, 做了很多注释, 好好看看就能搞懂

服务器端:

# coding: utf-8
import select
import socket
import Queue
from time import sleep# Create a TCP/IP
server = socket.socket(socket.AF\_INET, socket.SOCK\_STREAM)
server.setblocking(False)# Bind the socket to the port
server\_address = ('localhost', 8090)
print ('starting up on %s port %s' % server\_address)
server.bind(server\_address)# Listen for incoming connections
server.listen(5)# Sockets from which we expect to read
inputs = \[server\]# Sockets to which we expect to write
# 处理要发送的消息
outputs = \[\]# Outgoing message queues (socket: Queue)
message\_queues = {}while inputs:# Wait for at least one of the sockets to be ready for processingprint ('waiting for the next event')# 开始select 监听, 对input\_list 中的服务器端server 进行监听  # 一旦调用socket的send, recv函数,将会再次调用此模块readable, writable, exceptional = select.select(inputs, outputs, inputs)# Handle inputs# 循环判断是否有客户端连接进来, 当有客户端连接进来时select 将触发for s in readable:# 判断当前触发的是不是服务端对象, 当触发的对象是服务端对象时,说明有新客户端连接进来了# 表示有新用户来连接if s is server:# A "readable" socket is ready to accept a connectionconnection, client\_address = s.accept()print ('connection from', client\_address)# this is connection not serverconnection.setblocking(0)# 将客户端对象也加入到监听的列表中, 当客户端发送消息时 select 将触发inputs.append(connection)# Give the connection a queue for data we want to send# 为连接的客户端单独创建一个消息队列,用来保存客户端发送的消息message\_queues\[connection\] = Queue.Queue()else:# 有老用户发消息, 处理接受# 由于客户端连接进来时服务端接收客户端连接请求,将客户端加入到了监听列表中(input\_list), 客户端发送消息将触发# 所以判断是否是客户端对象触发data = s.recv(1024)# 客户端未断开if data != '':# A readable client socket has dataprint ('received "%s" from %s' % (data, s.getpeername()))# 将收到的消息放入到相对应的socket客户端的消息队列中message\_queues\[s\].put(data)# Add output channel for response# 将需要进行回复操作socket放到output 列表中, 让select监听if s not in outputs:outputs.append(s)else:# 客户端断开了连接, 将客户端的监听从input列表中移除# Interpret empty result as closed connectionprint ('closing', client\_address)# Stop listening for input on the connectionif s in outputs:outputs.remove(s)inputs.remove(s)s.close()# Remove message queue# 移除对应socket客户端对象的消息队列del message\_queues\[s\]# Handle outputs# 如果现在没有客户端请求, 也没有客户端发送消息时, 开始对发送消息列表进行处理, 是否需要发送消息# 存储哪个客户端发送过消息for s in writable:try:# 如果消息队列中有消息,从消息队列中获取要发送的消息message\_queue = message\_queues.get(s)send\_data \= ''if message\_queue is not None:send\_data \= message\_queue.get\_nowait()else:# 客户端连接断开了print "has closed "except Queue.Empty:# 客户端连接断开了print "%s" % (s.getpeername())outputs.remove(s)else:# print "sending %s to %s " % (send\_data, s.getpeername)# print "send something"if message\_queue is not None:s.send(send\_data)else:print "has closed "# del message\_queues\[s\]# writable.remove(s)# print "Client %s disconnected" % (client\_address)# # Handle "exceptional conditions"# 处理异常的情况for s in exceptional:print ('exception condition on', s.getpeername())# Stop listening for input on the connectioninputs.remove(s)if s in outputs:outputs.remove(s)s.close()# Remove message queuedel message\_queues\[s\]sleep(1)

客户端:

# coding: utf-8
import socketmessages \= \['This is the message ', 'It will be sent ', 'in parts ', \]server\_address \= ('localhost', 8090)# Create aTCP/IP socket
socks \= \[socket.socket(socket.AF\_INET, socket.SOCK\_STREAM), socket.socket(socket.AF\_INET,  socket.SOCK\_STREAM), \]# Connect thesocket to the port where the server is listeningprint ('connecting to %s port %s' % server\_address)
# 连接到服务器
for s in socks:s.connect(server\_address)for index, message in enumerate(messages):# Send messages on both socketsfor s in socks:print ('%s: sending "%s"' % (s.getsockname(), message + str(index)))s.send(bytes(message \+ str(index)).decode('utf-8'))# Read responses on both socketsfor s in socks:data \= s.recv(1024)print ('%s: received "%s"' % (s.getsockname(), data))if data != "":print ('closingsocket', s.getsockname())s.close()

写代码过程中遇到了两个问题, 一是如何判断客户端已经关闭了socket连接, 后来自己分析了下, 如果关闭了客户端socket, 那么此时服务器端接收到的data就是’', 加个这个判断。二是如果服务器端关闭了socket, 一旦在调用socket的相关方法都会报错, 不管socket是不是用不同的容器存储的(意思是说list_1存储了socket1, list_2存储了socket1, 我关闭了socket1, 两者都不能在调用这个socket了)

服务器端:

客户端:

​最后,如果你也想自学Python,可以关注我。

我还整理出了一套系统的学习路线,这套资料涵盖了诸多学习内容: 【扫描下方】领取!

在这里插入图片描述

包括:Python激活码+安装包、Python web开发,Python爬虫,Python数据分析,人工智能、自动化办公等学习教程。带你从零基础系统性的学好Python!开发工具,基础视频教程,项目实战源码,51本电子书籍,100道练习题等。相信可以帮助大家在最短的时间内,能达到事半功倍效果,用来复习也是非常不错的。
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/2501.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

JavaIO流操作

目录 简介 字节输入流 获取字节输入流 读 关闭输入流 字节输出流 获取字节输出流 写 换行符 刷新 关闭输出流 字符流输入流 获取字符输入流 读 关闭输入流 字符输出流 获取字符输出流 写 换行符 刷新 关闭输出流 简介 IO流分为两大派系: …

大数据之Hadoop集群

Hadoop集群介绍?Hadoop集群的优缺点及应用场景?Hadoop集群搭建?Hadoop架构? Hadoop集群介绍 Hadoop集群是由多台计算机(节点)组成的一个分布式计算系统,主要用于处理大规模的数据集。以下是对Ha…

项目推荐:指针切换器

小编的inscode部署项目:割绳子游戏。 更多精彩内容见InsCode - 让你的灵感立刻落地~ 介绍一下项目。 引言 在现代用户界面设计中,鼠标指针的样式和行为对用户体验有着重要的影响。传统的鼠标指针样式(如箭头、手形、等待图标等&#xff09…

D-ID 推出能模仿用户的头部动作以及实时互动的 AI 头像

D-ID 宣布推出两种新型 AI 头像 — — Express 和 Premium,旨在提升内容创作的灵活性和人性化。这些头像将为企业在营销、销售和客户支持等领域的视频制作提供便利。用户只需少量文本输入和视觉数据,即可生成更自然的商业视频。 Express 头像可以通过约一…

【C++系列】-----------内存管理

c内存管理(涉及:数据在内存中的分布、new和delete使用、动态内存管理等) 文章目录 c内存管理(涉及:数据在内存中的分布、new和delete使用、动态内存管理等)前言一、C/C内存分布二、C中动态内存管理2.1、 ne…

SpringBoot框架:作业管理系统构建之道

摘 要 使用旧方法对作业管理信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在作业管理信息的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。 这次开发的作业管理系统有管…

Linux字体更新 使用中文字体

问题描述,处理之前,中文乱码 处理后的结果 压缩需要上传的字体: 上传到LInux的字体目录,上传后解压出来 刷新字体: fc-cache -fv 测试是否正常 fc-list | grep "FontName"如果还不行 可以在代码里面指定字…

【书生.浦语实战营】——入门岛

【书生.浦语实战营】——入门岛_第一关_Linux基础 任务分布1. 本地vscode远程连接并进行端口映射端口映射What——何为端口映射How——怎么进行端口映射 2. Linux基础命令touch :创建文件mkdir :创建目录cd:进入 退出 目录pwd :确定当前所在目录cat:可以…

VirtualBox 解决虚拟机Cable Unplugged 无法上网问题

问题描述 VirtualBox 中的虚拟机无法上网,在虚拟机中查看网络设置显示 Cable Unplugged。 解决方案 选择VirtualBox 上方任务栏的控制->设置->网络,勾选接入网线即可解决。

win10下MMSegmentation自定义数据集

下载1.2.1版本: Releases open-mmlab/mmsegmentation GitHub 安装环境 本地torch环境为1.9.1 pip install -U openmim mim install mmengine mim install "mmcv>=2.0.0" 报mmcv版本不匹配的问题,形如:MMCV==X.X.X is used but incompatible. Please inst…

CSS网格布局

前言 希望元素按照网格的方式进行布局,最简单的方式就是利用网格布局,如图所示: 网格布局 设置网格布局的核心属性: ① display: grid 设置容器为网格布局容器(如果希望设置行内的网格容器,可以设置disp…

童年的玩具:燕麦时钟

也不知道是谁传下来的,燕麦时钟。 燕麦是野生的,通常在麦地里面的都被拔掉,但是土埂上面的还幸存下来。 这个燕麦成熟后,上面有个麦芒由直的变弯,越是90度,越成熟。 选一根90度的成熟麦芒。把下部插入一团…

如何在BSV区块链上实现可验证AI

​​发表时间:2024年10月2日 nChain的顶尖专家们已经找到并成功测试了一种方法:通过区块链技术来验证AI(人工智能)系统的输出结果。这种方法可以确保AI模型既按照规范运行,避免严重错误,遵守诸如公平、透明…

2024年还有多少人在使用PHP?

根据W3Techs的最新数据,2024年PHP仍然支持76.5%的网站,这一数字在一年内下降不到1%(截至2023年为77.3%)。 尽管这一数字有所下降,但这表明PHP仍然是Web开发中非常流行的语言。 根据JetBrains的调查,在过去…

在这里游玩和创造,见证实时互动和 AI 的融合爆发丨年末场 RTE Open Day@RTE2024 回顾

RTE2024 第十届实时互联网大会上周末在北京圆满结束了,不知道大家体验交流得如何?可能是因为本来入秋的北京悄然升温,又或者是那两天的观众都很热情,25-26 号的活动现场特别像是一场夏天的聚会。 RTE Open Day 马不停蹄来到了第五…

智能体联手微信,打造24小时在线的全能AI机器人,除了聊天,还能接商单

最近在我们的智能体学习群里,微信AI机器人成了小明星,它功能丰富,机智幽默,成为了大家的心头好😗 比如,它会非常热情的欢迎新入群的小伙伴,并且能够很机智的将小伙伴的名字巧妙地融入到欢迎词中…

采购退料单集成方案:从旺店通到金蝶云的API实现

14-采购退料单集成方案:旺店通旗舰奇门数据集成到金蝶云星空 在企业的供应链管理中,采购退料单的高效处理至关重要。为了实现这一目标,我们采用了轻易云数据集成平台,将旺店通旗舰奇门的数据无缝对接到金蝶云星空。本次分享的案例…

MyBatis的高级映射及延迟加载

多对一: 多种方式,常见的包括三种: 第一种方式:一条SQL语句,级联属性映射。 第二种方式:一条SQL语句,association。 第三种方式:两条SQL语句,分步查询。(这…

bugku中web题-source

Web安全解题基础三件套思路 信息收集与目录扫描 御剑扫描:探测网站目录结构,找潜在可访问路径,如管理员后台等目录。dirsearch扫描后台目录:配置参数后扫描,分析返回有意义状态码的目录,可能包含后台管理界…

Java中String的length与Oracle数据库中VARCHAR2实际存储长度不一致的问题

目录 一、根本原因 二、解决方案 一、根本原因 Oracle数据库新增数据的时候报如下错误: 先给大家看个小案例,这样更好去理解,下面是一段测试代码: 这里面我分别列举了三种字符串,中文,英文和数字以及两种…