socket function that loops AND returns something

Donn Cave donn at drizzle.com
Thu Sep 16 05:43:11 CEST 2004


Quoth Brad Tilley <bradtilley at usa.net>:
| I have a function that starts a socket server looping continuously 
| listening for connections. It works. Clients can connect to it and send 
| data.
|
| The problem is this: I want to get the data that the clients send out of 
| the loop but at the same time keep the loop going so it can continue 
| listening for connections. If I return, I exit the function and the loop 
| stops. How might I handle this?
|
|   def listen(ip_param, port_param):
|      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|      while 1:
|          print "\nWaiting for new connection...\n"
|          s.listen(1)
|          conn, addr = s.accept()
|          print "Client", addr[0], "connected and was directed to port", addr[1]
|          data = conn.recv(1024)
|          # I want to get 'data' out of the loop, but keep the loop going	
|          print "Client sent this message:", data
|          conn.close()

Well, some people would address this problem by spawning a thread
(and then they'd have two problems!  as the saying goes.)

It depends on what you want.  Your main options:

  -  store whatever state you need to resume, and come back
     and accept a new connection when you're done with the data -
        class SocketConnection:
            def __init__(self, ip_param, port_param):
                 ...
            def recv(self):
                ... accept
                ... recv
                ... close
                return data
  -  turn it upside down, call the processing function
       def listen(ip_param, port_param, data_function):
           ...
               data = conn.recv(1024)
               data = data_function(data)
               if data:
                   conn.send(data)
               conn.close()
           ...
  -  fork a new process (UNIX oriented.)
           ...
              pid = os.fork()
              if pid:
                  wait_for_these_pids_eventually.append(pid)
              else:
                  try:
                      conn, addr = s.accept()
                      s.close()
                      conn_function(conn)
                  finally:
                      os._exit(0)
  -  spawn a new thread (similar idea)

Processes and threads will allow your service to remain responsive
while performing tasks that take a long time, because these tasks
will run concurrently.  They do bring their own issues, though, and
it isn't worth it unless it's worth it, which only you can tell.
It's a pretty lengthy computation that takes so much time that a
thread or process is really called for.

If the inverted, functional approach suits your application, note
that you can use a Python class instance here to keep state between
connections - like,
     class ConnectionReceiver:
         ...
         def data_function(self, data):
             self.count = self.count + 1
             print >> sys.stderr, 'datum', self.count
             ...
     ...
     receiver = ConnectionReceiver()
     listen(ip_param, port_param, receiver.data_function)

	Donn Cave, donn at drizzle.com



More information about the Python-list mailing list