当前位置:
首页 > temp > python入门教程 >
-
02select监听服务端
# can_read, can_write, _ = select.select(inputs, outputs, None, None) # # 第一个参数是我们需要监听可读的套接字, 第二个参数是我们需要监听可写的套接字, 第三个参数使我们需要监听异常的套接字, 第四个则是时间限制设置. # # 如果监听的套接字满足了可读可写条件, 那么所返回的can,read 或是 can_write就会有值了, 然后我们就可以利用这些返回值进行随后的操作了。相比较unix 的select模型, 其select函数的返回值是一个整型, 用以判断是否执行成功. # # 第一个参数就是服务器端的socket, 第二个是我们在运行过程中存储的客户端的socket, 第三个存储错误信息。 # 重点是在返回值, 第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的 # list。 import select, socket, queue from time import sleep # 创造一个 TCP/IP连接 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 设置socket为异步模式。 server.setblocking(False) # 绑定IP地址和端口 # 创建一个IP,端口,本地IP server_address = ('localhost', 8090) print('starting up on %s port %s' % server_address) # 绑定IP和端口 server.bind(server_address) # 设置服务端监听数量 server.listen(3) inputs = [server] # 处理要发送的数据 outputs = [] # 输出的消息队列 message_queues = {} while inputs: # 等待至少一个连接开始调用线程 print("waiting for the next event") # 开始select监听,对input_list中的服务器端的server开始进行监听 # 一旦调用socket的send,recv函数,将会再次调用此模块 # 这里监控三个参数,第一个返回的是可读的list, 第二个存储的是可写的list, 第三个存储的是错误信息的 readable, writable, exceptional = select.select(inputs, outputs, inputs) # 处理输入 # 循环判断是否有客户端连接进来,当有客户端连接进来的时候select将进行触发 for s in readable: # 判断当前触发的是不是服务端对象,当触发的是服务端对象, 说明有新的客户端连接进来了 if s is server: # 和客户端建立连接 connection, client_address = s.accept() # 打印客户端的链接 print('connection from', client_address) # 设置socket为异步模式。 connection.setblocking(0) # 将客户端对象也加入到监听列表中,当客户端发送消息的时候select也会触发。 inputs.append(connection) # 为连接的客户端单独建立一个消息队列,用来保存客户端发送的消息 message_queues[connection] = queue.Queue() else: # 有老用户发送消息,处理接收 # 由于客户端连接进来的时候服务端接收客户端的请求,将客户端也加入到了监听列表。 # 客户端发送的消息将触发。 # 判断触发对象是否为客户端 # 接收客户端的信息 data = s.recv(1024) # 客户端没有断开 if data != '': # 一个可用的客户端发送了数据 print('received "%s" from %s' % (data, s.getpeername())) # 将接受到的消息放到对应的客户端的消息队列中 message_queues[s].put(data) # 将需要进行回复操作的socket放到output列表中,让select监听 # 这里我们如果收到消息将服务端添加进入输出列表。 # 然后select就会监听到, if s not in outputs: outputs.append(s) else: # 客户端被监听到有变化,不是有客户端传过来的消息,就是客户端断开了。 # 客户端断开了连接,将客户端的监听从input列表中移除 print('closing', client_address) if s in outputs: outputs.remove(s) inputs.remove(s) s.close() # 移除对应的socket客户端对象的消息队列 del message_queues[s] # 处理输出。 # 如果现在没有客户端的请求,也没有客户端发送消息时,开始对发送的消息列表进行处理。 # 判断是否需要发送消息。 # 存储哪个客户端发送了消息。 for s in writable: try: # 如果消息队列中有消息,就从消息队列中获取要发送的消息。 message_queue = message_queues.get(s) sent_data = '' if message_queues 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 connection inputs.remove(s) if s in outputs: outputs.remove(s) s.close() # Remove message queue del message_queues[s] sleep(1) 出处:https://www.cnblogs.com/cong12586/p/14071328.html
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
SQL Server -- 解决存储过程传入参数作为s
关于JS定时器的整理
JS中使用Promise.all控制所有的异步请求都完
js中字符串的方法
import-local执行流程与node模块路径解析流程
检测数据类型的四种方法
js中数组的方法,32种方法
前端操作方法
数据类型
window.localStorage.setItem 和 localStorage.setIte
如何完美解决前端数字计算精度丢失与数