# 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)

























文章来源于网络 ,如有侵权请联系站长QQ61910465删除
本文版权归QU快排Www.seoGurubLog.com 所有,如有转发请注明来出,竞价开户托管,seo优化请联系QQ▲61910465