I am working on writing a network application in Python. I previously worked on the use of blocking sockets, but after a better understanding of the requirements and concepts, I want to write an application using non-blocking sockets and, therefore, an event driven server.
I understand that functions in the select module in Python should be used to conveniently see which socket interests us, etc. To the fact that I basically tried to flip a few examples of an event-driven server, and I came across this:
""" An echo server that uses select to handle multiple clients at a time. Entering any line of input at the terminal will exit the server. """ import select import socket import sys host = '' port = 50000 backlog = 5 size = 1024 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((host,port)) server.listen(backlog) input = [server,sys.stdin] running = 1 while running: inputready,outputready,exceptready = select.select(input,[],[]) for s in inputready: if s == server:
Parts that I did not seem to understand are as follows:
In the code snippet inputready,outputready,exceptready = select.select(input,[],[]) I believe that the select() function returns three possible empty lists of expected objects for input, output and exceptional conditions. Therefore, it makes sense that the first argument to the select() function is a list containing the server socket and stdin. However, when I run into confusion, in the else block of the code.
Since we are looping over the inputready socket list, it is clear that the select() function will select a client socket that is ready to read. However, after we read the data using recv() and find that the socket actually sent the data, we would like to send it back to the client. My question is, how can we write to this socket without adding it to the list passed as the second argument to the select() function call? Sense, how can we call send() directly on a new socket without registering it with select() as a writable socket?
In addition, why do we focus only on read-only sockets (in this case already entered)? Isn't it even necessary to iterate over the outputready list to see which sockets are ready for writing? Obviously I'm missing something here.
It would also be useful if someone could explain the operation of select() in more detail or point to good documentation.
Thanks.