简体   繁体   中英

Python TCP Sockets: How to know if a specific connection has sent information

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:

Thread 1

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

Thread 2

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM