Handling more than one request on a socket

brueckd at tbye.com brueckd at tbye.com
Wed Aug 29 00:13:25 EDT 2001


> I'm trying to come to grips with the issue of dealing with sockets,
> or, more precisely, a socket that can accept and process 'n' number of
> requests on a particular address.
>
> Right now I'm going the route of opening an inet streaming socket,
> binding it to the port, and listen()ing for requests. For example, for
> a telnet port:
>
>    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>    s.bind(('', 23))
>    s.listen(1)
>
> ... then ... ?  I've tried a number of approaches, but so far all I
> can get to work is a single connection at a time, and in most cases
> it's good for one recv().
>
> This is an issue I'm going to be looking at in a lot of cases, so I'd
> like to iron it out now if I can. Any suggestions on where to start?

Hi Jeff,
You're getting close - you can either handle multiple connections via
threads or by using a call to select or poll.

With threads, it goes something like this (untested):

import threading, socket

def handler(s):
  'Do whatever you want with this socket'
  print 'Received',s.recv(4096)
  s.close()

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 5555))
s.listen(1)

while 1:
  print 'Listening for connections'
  newSock, newFrom = s.accept()
  print 'Got connection from', newFrom
  threading.Thread(target=handler, args=(newSock,)).start()

That's about it - you can put whatever you want in handler of course.
Also, there's some great code to do all this in the SocketServer module,
including a mixin class that makes it very easy to do all of the above for
you (this newsgroup had a thread on this very topic within the last week).
With SocketServer you don't implement the server itself but a request
handler class that the server instantiates each time a request comes in.
(essentially you just implement the equivalent of the handler method
above).

To handle multiple connections without threads (which may be a good idea
if you need a higher performance solution and are mostly I/0 bound, like
if you're writing an HTTP proxy server), you can use the poll call in the
select module (I think this was added in Python 2.0. If you're using an
older version you can use select.select or the poll module). Anyway, this
approach basically involves creating a poller object (via select.poll()),
and then registering one or more sockets with the poller. You then call
its poll function and it returns a list of sockets on which you can read
or write without blocking (it actually returns a list of tuples, the first
item in the tuple is the file descriptor number and the second is a set of
flags indicating whether you can read, write, or both without blocking on
that socket).

Like I said, this approach works well for higher performance stuff, but is
a little more involved and makes you approach the problem from a slightly
different angle. If you're interested in this, check out the asyncore and
asynchat modules - they build a framework around select and poll so things
are much easier for you. I don't dare post untested code on here because I
know I'll get it wrong (it's slightly more complex than using
SocketServer), but if you're interested I'd be happy to dig up some simple
samples for you (both doing select/poll yourself and using asyncore and
asynchat).

HTH,
-Dave





More information about the Python-list mailing list