关于Socket中的Select使用理解
以下是代码和中文注释的个人理解
import socket, select, Queueserver=('192.168.2.100',10086)#创建TCP/TP Socket
sock_ser=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#设置不阻塞监听
sock_ser.setblocking(False)
sock_ser.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#绑定IP地址
sock_ser.bind(server)
#监听连接
sock_ser.listen(10)#准备用来读取数据的Socket,客户端向服务端的读端口写
incomes=[sock_ser]
#准备用来写的Socket,客户端从写Socket读
outputs=[]"""
写出消息的队列,由于select是循环机制,所以每个独立的outputs都需要一个队列来保存待写出的数据,
等到轮回到自己的时候写出
"""
msg_que={}#超时时间。
timeout=20#服务端的Socket用来接受服务端的连接,并用作与循环。
while incomes:"""先等待至少一个Socket的数据处理,Select返回当前三个列表。这三个数据来自于可读,可写,返回的错误。Select监听并等待网络活动。如果有网络活动则开始执行"""rs,ws,es=select.select(incomes,outputs,incomes,timeout)if not(rs or ws or es):print "error: timeout...."breakfor s in rs:"""此处的rs存储很多Socket,开始存储只有服务端本身的Socket,用于与客户端建立新的连接。并将客户端建立好的连接存储在incomes中,incomes会返回给rs。存储的的客户端,会被用于收发数据。"""#rs队列中按个读取,如果是服务端的socket就用那个与建立新的连接。if s is sock_ser:conn,addr=s.accept()print "connect by ",addrconn.setblocking(False)incomes.append(conn)#为接入的客户端提供一个队列来发送回复给客户端的数据msg_que[conn]=Queue.Queue()#如果不是服务端的socket,是客户端建立连接的Socket,就收数据,并判断是否断开。else:data=s.recv(1024)#有数据就收数据if data:print "receive client ",datamsg_que[s].put(data)if s not in outputs:outputs.append(s)#可读的socket没有数据发送,则说明客户端断开连接,我们删除这个客户端。else:if s in outputs:outputs.remove(s)incomes.remove(s)s.close()del msg_que[s]#写操作,查看队列里面是否有东西,并发送到对应的Socket.for s in ws:try:msg = msg_que[s].get_nowait()except Queue.Empty:#因为是轮回的,当前面连接断开后,写的socket尚未删除,这一步还是要执行的,所以最后输出了几个EMPTY。print 'msg empty'outputs.remove(s)else:s.send("from server :"+msg)for s in es:print "except",s.getpeername()if s in incomes:incomes.remove(s)if s in outputs:outputs.remove(s)s.close()del msg_que[s]