Reputation: 1418
I have a multi-threaded Python 3 application that on thread #1 accepts TCP socket communications. Thread #2 will check all current connections if they have anything to receive, then act accordingly.
So, currently I have a list called all_connections
which is a list of accepted socket connection objects.
Using for connection in all_connections:
I can loop through all the connection objects. I know I use conn.recv(256)
to check if there is anything ready to recive on this socket. Will this block the loop though untill there is something to receive? I have set conn.setblocking(1)
beforehand although Im unsure if this is the best way to get around it:
Here is some example code:
self.all_connections = [] # init a list to hold connection objs
while 1:
try:
conn, address = self.socket.accept()
conn.setblocking(1) # non blocking
except Exception as e:
continue
self.all_connections.append(conn) # Save the connection object
while True:
for connection in self.all_connections:
received = connection.recv(256)
return
So, I'm only interested in connections that have actually sent something, as I will be sending them something back most likely.
I know I can use select.select
in order to check if there is anything to receive on the socket, but that wouldn't help me reference the specific connection.
Upvotes: 1
Views: 667
Reputation: 87134
Yes, read()
will block; this is the default behaviour. Calling socket.setblocking(1)
actually enables blocking, which is opposite of what you wanted. setblocking(False)
will set non-blocking mode. I/O on non-blocking sockets requires that you use exception handling.
A better way, and you are already headed in the right direction, is to use select()
. You do in fact know which socket sent data because select()
returns a list of sockets that are available for reading, writing, or that have an error status. You pass to select()
a list of the sockets that you are interested in and it returns those that are available for I/O. Here is the function signature:
select(...)
select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)
So the code in thread 2 would look something like this:
from select import select
while True:
rlist, wlist, xlist = select(self.all_connections, [], [])
for connection in rlist:
received = connection.recv(256)
The above code only checks for readable sockets in the list of all connections and reads data from those that are ready. The read will not block.
Upvotes: 2