千家信息网

如何使用socket的select模型

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,本篇内容主要讲解"如何使用socket的select模型",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何使用socket的select模型"吧!Sele
千家信息网最后更新 2026年11月01日如何使用socket的select模型

本篇内容主要讲解"如何使用socket的select模型",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何使用socket的select模型"吧!

Select模型在windows下和linux下都可以使用,更高级的epoll模型只能在linux下使用。

在开始select之前,先纠正一个错误,MsgContainer中的__check_head函数应当改为下面的样子:

def __check_head(self):
if self.msg_len == 0 and len(self.msgpond) > 5:
self.__get_msg_len()
self.__get_msg()

这个错误竟然没有人反馈,可见,大家只是看一看,都没有实际验证或使用。。。。。

select模型其实很好理解,我们给它三个数组,数组里存放的是socket,每一次的select,模型会从这三个数组中分别挑出来可读的,可写的,发生异常的socket,并分别放入到三个数组中,这样,应用层遍历这三个数组,做相应的操作。看代码:

#coding=utf-8
import select
import socket
import sys
from MsgContainer import MsgContainer

def start_server(port):
HOST='0.0.0.0'
PORT=port

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#server.setblocking(False)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR , 1)
server.bind((HOST,PORT)) #套接字绑定的IP与端口
server.listen(10) #开始TCP监听

inputs = [server] #存放需要被检测可读的socket
outputs = [] #存放需要被检测可写的socket
message_queues = {} #存储可发送的数据

while inputs:
readable , writable , exceptional = select.select(inputs, outputs, inputs)
# 可读
for s in readable:
if s is server:
connection, client_address = s.accept()
inputs.append(connection)
message_queues[connection] = MsgContainer()
else:
data = s.recv(3) #故意设置的这么小
if data :
message_queues[s].add_data(data)
#已经从这个socket当中收到数据,如果你想写,那么就将其加入到outputs中,等到select模型检查它是否可写
if s not in outputs:
outputs.append(s)
else:
#收到为空的数据,意味着对方已经断开连接,需要做清理工作
if s in outputs :
outputs.remove(s)
inputs.remove(s)
s.close()
del message_queues[s]

#可写
for w in writable:
#此处一定要判断w是否真的可写,有可能w既在readable中,也在writable中,而读到的数据是空,这样其实是关闭了连接
if not w in message_queues:
continue
mc = message_queues[w]
msgs = mc.get_all_msg()
print msgs
for msg in msgs:
msg = mc.pack_msg(msg)
w.send(msg)
mc.clear_msg()
outputs.remove(w)
# 异常
for s in exceptional:
inputs.remove(s)
if s in outputs:
outputs.remove(s)
s.close()
del message_queues[s]

if __name__ == '__main__':
if len(sys.argv) == 2:
port = int(sys.argv[1])
start_server(port)
else:
print u'请输入端口号'

这里就几个你可能疑惑的问题做重点讲解。

发现一个可读的socket时,如何去接收数据呢?此前我提供的例子,都是在wihle循环里不停的读取,在select模型中,仍然可以这样使用,但是要注意,需要把socket设置为非阻塞的,这样才能从while循环中退出来。本篇的例子没有使用while循环,而是每次读取3个字节的数据,如果对方发过来的数据长度是9,那么第一次读取后,接收缓冲区里还有6个字节的数据可读,在下一次select操作过程中,这个socket仍然会被放入到readtable中,这样,就可以继续读剩下的数据了。

在遍历writable数组时,一定要判断该socket是不是真的可写。我在实际测试中发现了这样的情况,一个socket既在readtable中也在writable中,但在读的时候,数据是空,对方关闭了连接,此时在去写数据,就会发生错误,所以我通过对message_queues做了一个简单的检查来判断socket是不是真的可写。

在每一次写操作执行后,都从socket从writable中删除,这样做的原因很简单,该写的数据已经写完了,如果不删除,下一次select操作时,又会把他放入到writable中,可是现在已经没有数据需要写了啊,这样做没有意义,只会浪费select操作的时间,因为它要遍历outputs中的每一个socket,判断他们是否可写以决定是否将其放入到writtable中。

在exceptional中,是发生错误和异常的socket,有了这个数组,就在也不用操心错误和异常了,不然程序写起来非常的复杂,有了统一的管理,发生错误后的清理工作将变得非常简单。

到此,相信大家对"如何使用socket的select模型"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

数据 模型 数组 错误 三个 实际 对方 循环 例子 内容 字节 学习 工作 检查 检测 复杂 更深 高级 不用 兴趣 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 亿人帮互联网科技有限公司 哈尔滨大商圈互联网科技有限公司 河南云网互联网络科技有限公司 山东特亿宝互联网科技有限公司 云之行互联网科技 成都互联网科技公司 掌上梦互联网科技 互联网科技股有哪些 中国最先进互联网科技公司 科技赋能互联网健康 西藏七维空间互联网科技有限公司 天速互联网络科技有限公司 昭通云南众福互联网科技有限公司 银川新华互联网科技职业技术培训学校图片 栖莱科技互联网股份有限公司 湖北码尼互联网科技有限公司电话 昊天互联网科技有限公司 互联网科技与大数据专业 链环科技传统企业怎么转型互联网 银川新华互联网科技学校招聘 互联网科技工作委员会 科技互联网政务服务 西安互联网科技 齐家互联网科技 壕鑫互联网络科技 科技互联网大厂 南平创想时代互联网科技有限公司 明优互联网科技有限公司 广东工业互联网大赛深圳学泰科技 广州全民伙伴互联网科技有限公司
0