To understand the select.select module is essentially to understand its parameters and its three return values.
The select() method receives and monitors three communication lists. The first is all input data, that is, data sent from outside, the second is monitoring and receiving all outgoing data, and the third is monitoring error information.
I've been looking for this parameter explanation of select.select on the internet, but I really don't have it. Ouch..... I've made a hard analysis of it myself.
readable, writable, exceptional = select.select(inputs, outputs, inputs)
The first parameter is the socket on the server side, the second is the socket on the client side that we store in the running process, and the third is the error message.
The focus is on the return value, the first returns a readable list, the second stores a writable list, and the third stores error information.
list.
This does not need to be studied in depth, look at the code under its own analysis can have a general understanding.
All the code about select.select on the Internet is the same, but some of it doesn't work or is incomplete. I've rewritten a working program myself, and I've made a lot of annotations, so I can understand it after a good look.
Server side:
# coding: utf-8 import select import socket import Queue from time import sleep # Create a TCP/IP server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setblocking(False) # Bind the socket to the port server_address = ('localhost', 8090) print ('starting up on %s port %s' % server_address) server.bind(server_address) # Listen for incoming connections server.listen(5) # Sockets from which we expect to read inputs = [server] # Sockets to which we expect to write # Processing messages to be sent outputs = [] # Outgoing message queues (socket: Queue) message_queues = {} while inputs: # Wait for at least one of the sockets to be ready for processing print ('waiting for the next event') # start select Monitor, Yes input_list Server side in server Monitor readable, writable, exceptional = select.select(inputs, outputs, inputs) # Handle inputs # Loop to determine if there is a client connection in, When a client connection comes in select Will trigger for s in readable: # Determine if the current trigger is a server object?, When the triggered object is a server-side object,Explain that a new client is connected in # Represents a new user to connect to if s is server: # A "readable" socket is ready to accept a connection connection, client_address = s.accept() print ('connection from', client_address) # this is connection not server connection.setblocking(0) # Add client objects to the list of listeners, When the client sends a message select Will trigger inputs.append(connection) # Give the connection a queue for data we want to send # Create a separate message queue for the connected client to store the messages sent by the client message_queues[connection] = Queue.Queue() else: # Old users send messages, Processing acceptance # Because the server receives the client connection request when the client connection comes in, the client is added to the listening list.(input_list), Client sending message will trigger # So is it a client object trigger? data = s.recv(1024) # Client not disconnected if data != '': # A readable client socket has data print ('received "%s" from %s' % (data, s.getpeername())) # Put the received message into the corresponding socket In the message queue of the client message_queues[s].put(data) # Add output channel for response # A reply operation will be required socket put to output List, Give Way select Monitor if s not in outputs: outputs.append(s) else: # The client disconnected, Listen to the client input List Removal # Interpret empty result as closed connection print ('closing', client_address) # Stop listening for input on the connection if s in outputs: outputs.remove(s) inputs.remove(s) s.close() # Remove message queue # Remove corresponding socket Message Queuing for Client Objects del message_queues[s] # Handle outputs # If there are no client requests now, When no client sends a message, Start processing the list of sent messages, Do you need to send a message? # Store which client sent the message for s in writable: try: # If there is a message in the message queue,Get the message to be sent from the message queue message_queue = message_queues.get(s) send_data = '' if message_queue is not None: send_data = message_queue.get_nowait() else: # The client connection was disconnected print "has closed " except Queue.Empty: # The client connection was disconnected 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" # Handling exceptions 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)
Client:
# coding: utf-8 import socket messages = ['This is the message ', 'It will be sent ', 'in parts ', ] server_address = ('localhost', 8090) # Create aTCP/IP socket socks = [socket.socket(socket.AF_INET, socket.SOCK_STREAM), socket.socket(socket.AF_INET, socket.SOCK_STREAM), ] # Connect thesocket to the port where the server is listening print ('connecting to %s port %s' % server_address) # Connect to the server for s in socks: s.connect(server_address) for index, message in enumerate(messages): # Send messages on both sockets for s in socks: print ('%s: sending "%s"' % (s.getsockname(), message + str(index))) s.send(bytes(message + str(index)).decode('utf-8')) # Read responses on both sockets for s in socks: data = s.recv(1024) print ('%s: received "%s"' % (s.getsockname(), data)) if data != "": print ('closingsocket', s.getsockname()) s.close()
There are two problems in the process of coding. One is how to judge that the client has closed the socket connection. Then I analyze myself. If the client socket is closed, then the data received by the server is', add this judgment. Second, if the socket is closed on the server side, it will make an error when calling the relevant method of socket, regardless of whether the socket is stored in different containers (that is to say, list_1 stores socket1, list_2 stores socket1, I close socket1, neither of them can call the socket).
Server side:
Client: