在实际开发中,经常会遇到select 和 socket进行搭配使用,在此个人做一个小结
一. select函数
1 函数原型
readable, writeable, exceptionable = select.select(rlist, wlist, xlist,timeout)
入参的前三个是三个列表,代表要监听的列表,通常第一个是读列表, 第二个是写列表,第三个则是异常列表,第四个代表select阻塞的时间(s)
返回值也是三个列表,分别是是监听列表中发生改变的成员,例如 rlist中一共监听了100个socket,如果有2个socket接收到消息,则readable中就应该有2个成员
但是特别注意的是,wlist中的所有成员都会复制到writeable
2 函数的实际应用--tcp--server
该脚本可以实现多客户端连接进行交互
import socket import select import sys # import queue import Queue import signal def server_start(server_ip, sever_port): try: # create a server socket /tcp server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # reuse socket # bind the server socket server_socket.bind((str(server_ip), int(sever_port))) server_socket.setblocking(False) # socket is non_blocking # set the max listen client number = 10 and start listen server_socket.listen(10) except socket.error as err: print("server start error, reason = " + str(err)) sys.exit(1) rlist = [server_socket] # put the server_socket to list wlist = [] message_queues = {} # store the message with clients and server client_queues = {} # store the client's address while True: try: timeout = 3 # if no event occur, select function will be return readable, writeable, exceptionable = select.select(rlist, wlist, rlist, timeout) print("select again") except select.error as err: print("select module init error, reason = " + str(err)) sys.exit(1) # handle the readable for s in readable: # new client is coming if s is server_socket: client_socket, client_address = s.accept() client_socket.setblocking(False) rlist.append(client_socket) message_queues[client_socket] = Queue.Queue() # create a message queue for new client client_queues[client_socket] = client_address # store the new client address print("new client is connecting, client is " + str(client_address)) # new data is coming or client is disconnected else: try: # receive data data_buff = s.recv(1024) except socket.error as err: print("receive data err!" + str(client_queues[s])) if data_buff: print(str(client_queues[s]) + "coming data, data = " + str(data_buff)) message_queues[s].put(data_buff) # put new data to message queue if s not in wlist: # update the wlist to handle the recived data wlist.append(s) else: # client is disconnected print("a client is disconnected " + str(client_queues[s])) del message_queues[s] del client_queues[s] rlist.remove(s) if s in wlist: wlist.remove(s) if s in writeable: writeable.remove(s) # handle the writeable for s in writeable: try: msg_que = message_queues.get(s) # get the message queue if msg_que is not None: # the queue is exist while not msg_que.empty(): # handle the message until the queue is empty msg = msg_que.get_nowait() # get the msg from message queue # do something.... s.send(msg + str(client_queues[s])) print("send data, data = " + str(msg + str(client_queues[s]))) print("exit") wlist.remove(s) # no message in queue except Queue.Empty: # client socket is disconnected wlist.remove(s) # update the wlist # handle the exceptionable for s in exceptionable: print("error!" + "(" + str(client_queues[s]) + ")") rlist.remove(s) if s in wlist: wlist.remove(s) del message_queues[s] del client_queues[s] pass if __name__ == '__main__': signal.signal(signal.SIGINT, quit) signal.signal(signal.SIGTERM, quit) server_start("10.74.133.94", "8080") while True: pass