Python的select使用关键点就select模块的select函数
import select
readables,writeables,exceptions=select.select(readable_list,writeable_list,exception_list,time_out) #1
每执行 1 这句话话,
情况一:
time_out为空的情况下,select会监听:
readable_list中的资源是否可读,将读就绪的资源返回到readables
writeable_list中的资源是否可写,将写就绪的资源返回到writeables
exception_list中的资源是否发生异常,将发生异常的资源放入exceptions
当所有资源都没有就绪的时候,select.select会阻塞当前线程,直到有某个资源就绪,然后返回
情况二:
time_out不为空的情况下,select会监听:
readable_list中的资源是否可读,将读就绪的资源返回到readables
writeable_list中的资源是否可写,将写就绪的资源返回到writeables
exception_list中的资源是否发生异常,将发生异常的资源放入exceptions
当所有资源都没有就绪的时候,select.select会阻塞当前线程,直到在time_out时间内有某个资源就绪,然后返回;如果在timeout时间内没有资源就绪,那就返回三个空列表,也就是readables=writerables=exceptisons=[]
import select
import socket
import time
SERVER_HOST=('127.0.0.1',9999)
class Select_Server_01:
'''
使用select和可读队列,可写队列实现服务器
'''
def __init__(self):
#创建套接字
self.server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定端口
self.server_socket.bind(SERVER_HOST)
#设置为监听套接字
self.server_socket.listen(5)
#可读就绪资源列表
self.readable_list=[self.server_socket]
#可写就绪资源列表
self.writeable_list=[]
'''
存储客户端socket传递过来的参数
存储结构如下
键为:客户端socket对象,值为socket对象传入的值
'''
self.client_socket_args={}
def handle_request(self,request_args):
#根据传入参数返回对应的参数
return "{}时刻,经过不负责任的socket处理过的数据:{}".format(time.time(),request_args)
'''
服务器运行核心,通过while循环
'''
def run(self):
"""
主循环,不断循环处理可读与可写队列
:return:
"""
while True:
#select检查并返回可读与可写列表中那些就绪的socket
readables,writerables,exceptions=select.select(self.readable_list,self.writeable_list,[])
#处理每个可读的socket
for readable_item in readables:
if readable_item==self.server_socket: #如果可读就绪的是服务器socket,则表示有新的客户端接入
client_socket,client_socket_address=readable_item.accept()
#将新的客户端socket存入可读列表
self.readable_list.append(client_socket)
print('接收到新socket:{}'.format(client_socket))
else: #除了服务器socket就是客户端socket可读了,我们这里接收一下客户端socket数据(这里是普通参数)
recv_data=readable_item.recv(1024).decode('utf-8') #这是一个堵塞操作,客户端最好不要一次发送太多的数据
if recv_data=='':
#如果客户端发送空字符串,表示自己要关闭,所以我们要清除这个客户端
#先关闭掉它
try:
readable_item.close()
except:
pass
#从客户端请求参数列表中清除
if readable_item in self.client_socket_args:
del self.client_socket_args[readable_item]
#从可读队列中清除
if readable_item in self.readable_list:
self.readable_list.remove(readable_item)
#从可写队列中清除
if readable_item in self.writeable_list:
self.writeable_list.remove(readable_item)
#从本轮的写就绪队列中删除(因为我们接下来会处理可写socket)
if readable_item in writerables:
writerables.remove(readable_item)
print('清除socket:{}'.format(readable_item))
elif recv_data!='CLOSE_SERVER_ZHOUYUQING':
#将请求参数存入客户端请求参数字典
self.client_socket_args[readable_item]=recv_data
#接下来我们要将客户端socket放入可写队列
if readable_item not in self.writeable_list:
self.writeable_list.append(readable_item)
print('处理socket:{}'.format(readable_item))
else: #客户端发过来是关闭指令
self.close()
return
#处理每个可写的socket
for writeable_item in writerables:
#获取这个socket对应传入参数
client_send_data=self.client_socket_args.get(writeable_item)
#向可写socket发送数据
print('当前关于该socket:{} 的传入参数是:{}'.format(writeable_item,client_send_data))
writeable_item.send(self.handle_request(client_send_data).encode('utf-8')) #阻塞操作
print('发送数据给:{}'.format(writeable_item))
#处理完这个可读socket后从可读队列中删除,知道它再次发送请求参数过来才会被添加到可读队列中
self.writeable_list.remove(writeable_item)
'''
关闭select_socket服务器
'''
def close(self):
#关闭所有存在的socket
for _socket in self.readable_list+self.writeable_list:
try:
_socket.close()
except:
pass
print('服务器执行关闭所有操作')
class Client_Socket_01:
'''
测试客户端socket
'''
def __init__(self):
self.client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def run(self,info,num):
self.client_socket.connect(SERVER_HOST)
for _ in range(num):
self.client_socket.send(info.encode('utf-8'))
print('\n\n {} 接收响应:{}\n\n'.format(info,self.client_socket.recv(1024).decode('utf-8')))
#发送关闭动作(发送一个为空字符串)
self.client_socket.send(''.encode('utf-8'))
try:
self.client_socket.close()
except:
pass
import multiprocessing
def main_01():
#先启动服务器
server_socket=Select_Server_01()
multiprocessing.Process(target=server_socket.run).start()
#启动测试客户端
client_socket_01=Client_Socket_01()
multiprocessing.Process(target=client_socket_01.run,args=('测试客户端1',1)).start()
client_socket_02=Client_Socket_01()
multiprocessing.Process(target=client_socket_02.run,args=('测试客户端2',3)).start()
client_socket_03=Client_Socket_01()
multiprocessing.Process(target=client_socket_03.run,args=('测试客户端3',6)).start()
client_socket_04=Client_Socket_01()
multiprocessing.Process(target=client_socket_04.run,args=('测试客户端4',9)).start()
#创建一个客户端发送一个关闭指令给服务器
time.sleep(30) #这句话很重要,你不要一上来就把服务器关了
final_client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
final_client_socket.connect(SERVER_HOST)
final_client_socket.send('CLOSE_SERVER_ZHOUYUQING'.encode('utf-8'))
try:
final_client_socket.close()
except:
pass
print('-------------------------->>>>>>>>>>>>>>>>执行关闭服务器完毕')
"""
执行:
main_01()
执行结果:
接收到新socket:
接收到新socket:
处理socket:
当前关于该socket: 的传入参数是:测试客户端1
发送数据给:
测试客户端1 接收响应:1548409232.0193949时刻,经过不负责任的socket处理过的数据:测试客户端1
处理socket:
当前关于该socket: 的传入参数是:测试客户端2
发送数据给:
测试客户端2 接收响应:1548409232.0195627时刻,经过不负责任的socket处理过的数据:测试客户端2
处理socket:
当前关于该socket: 的传入参数是:测试客户端2
发送数据给:
测试客户端2 接收响应:1548409232.0199127时刻,经过不负责任的socket处理过的数据:测试客户端2
处理socket:
当前关于该socket: 的传入参数是:测试客户端2
发送数据给:
接收到新socket:
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
发送数据给:
测试客户端3 接收响应:1548409232.0201845时刻,经过不负责任的socket处理过的数据:测试客户端3
测试客户端2 接收响应:1548409232.020043时刻,经过不负责任的socket处理过的数据:测试客户端2
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
发送数据给:
测试客户端3 接收响应:1548409232.020338时刻,经过不负责任的socket处理过的数据:测试客户端3
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
发送数据给:
接收到新socket:
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
发送数据给:
测试客户端4 接收响应:1548409232.0205855时刻,经过不负责任的socket处理过的数据:测试客户端4
测试客户端3 接收响应:1548409232.020468时刻,经过不负责任的socket处理过的数据:测试客户端3
处理socket:
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
测试客户端3 接收响应:1548409232.0207088时刻,经过不负责任的socket处理过的数据:测试客户端3
发送数据给:
当前关于该socket: 的传入参数是:测试客户端4
发送数据给:
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
测试客户端3 接收响应:1548409232.0208163时刻,经过不负责任的socket处理过的数据:测试客户端3
发送数据给:
处理socket:
当前关于该socket: 的传入参数是:测试客户端3
测试客户端3 接收响应:1548409232.0208836时刻,经过不负责任的socket处理过的数据:测试客户端3
发送数据给:
测试客户端4 接收响应:1548409232.0207596时刻,经过不负责任的socket处理过的数据:测试客户端4
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
发送数据给:
测试客户端4 接收响应:1548409232.0210006时刻,经过不负责任的socket处理过的数据:测试客户端4
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
发送数据给:
测试客户端4 接收响应:1548409232.0211372时刻,经过不负责任的socket处理过的数据:测试客户端4
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
发送数据给:
测试客户端4 接收响应:1548409232.021273时刻,经过不负责任的socket处理过的数据:测试客户端4
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
测试客户端4 接收响应:1548409232.0214124时刻,经过不负责任的socket处理过的数据:测试客户端4
发送数据给:
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
测试客户端4 接收响应:1548409232.021508时刻,经过不负责任的socket处理过的数据:测试客户端4
发送数据给:
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
测试客户端4 接收响应:1548409232.0216038时刻,经过不负责任的socket处理过的数据:测试客户端4
发送数据给:
处理socket:
当前关于该socket: 的传入参数是:测试客户端4
测试客户端4 接收响应:1548409232.0217009时刻,经过不负责任的socket处理过的数据:测试客户端4
发送数据给:
-------------------------->>>>>>>>>>>>>>>>执行关闭服务器完毕
接收到新socket:
服务器执行关闭所有操作
"""