start a multi-sockets server (a socket/per thread) with different ports but same host

zxo102 zxo102 at gmail.com
Sat Aug 12 13:44:29 EDT 2006


Jean-Paul,
Thanks a lot. The code is working. The python twisted is new to me too.
Here are my three more questions:
1. Since the code need to be started in a wxpyhon GUI (either by
clicking a button or up with the GUI),  do I have to run the code in a
thread (sorry, I have not tried it yet)?
2. How can I grab the client data in the code? Can you write two lines
for that? I really appreciate that.
3. After I change
self.transport.write(''.join(self.data))
   to
self.transport.write(''.join(data))
  and scan all the ports with the following code twice (run twice).
First round scanning says "succefully connected". But second round
scanning says "failed". I have to restart your demo code to make it
work.

Ouyang


import sys, threading, socket

class scanner(threading.Thread):
   tlist = []  # list of all current scanner threads
   maxthreads = int(sys.argv[2])  # max number of threads we're
allowing
   evnt = threading.Event()  # event to signal OK to create more
threads
   lck =  threading.Lock()  # lock to guard tlist
   def __init__(self,tn,host):
      threading.Thread.__init__(self)
      #self.threadnum = tn  # thread ID/port number
      self.threadnum = 2000+tn  # thread ID/port number
      self.host = host  # checking ports on this host
   def run(self):
      s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
      try:
         s.connect((self.host, self.threadnum))
         print "%d:  successfully connected" % self.threadnum
         s.close()
      except:
         print "%d:  connection failed" % self.threadnum
      # thread is about to exit; remove from list, and signal OK if we
      # had been up against the limit
      scanner.lck.acquire()
      scanner.tlist.remove(self)
      print "%d:  now active --" % self.threadnum, scanner.tlist
      if len(scanner.tlist) == scanner.maxthreads-1:
         scanner.evnt.set()
         scanner.evnt.clear()
      scanner.lck.release()
   def newthread(pn,hst):
      scanner.lck.acquire()
      sc = scanner(pn,hst)
      scanner.tlist.append(sc)
      scanner.lck.release()
      sc.start()
      print "%d:  starting check" % pn
      print "%d:  now active --" % pn, scanner.tlist
   newthread = staticmethod(newthread)

def main():
   host = sys.argv[1]
   #for i in range(1,100):
   for i in range(20):
      scanner.lck.acquire()
      print "%d:  attempting check" % i
      # check to see if we're at the limit before starting a new thread
      if len(scanner.tlist) >= scanner.maxthreads:
         # too bad, need to wait until not at thread limit
         print "%d:  need to wait" % i
         scanner.lck.release()
         scanner.evnt.wait()
      else:
         scanner.lck.release()
      scanner.newthread(i,host)
   for sc in scanner.tlist:
      sc.join()

if __name__ == '__main__':
    main()






Jean-Paul Calderone 写道:

> On 12 Aug 2006 09:00:02 -0700, zxo102 <zxo102 at gmail.com> wrote:
> >Hi,
> >   I am doing a small project using socket server and thread in python.
> > This is first time for me to use socket and thread things.
> >   Here is my case. I have 20 socket clients.  Each client send a set
> >of sensor data per second to a socket server.  The socket server will
> >do two things: 1. write data into a file via bsddb; 2. forward the data
> >to a GUI written in wxpython.
> >   I am thinking the code should work as follow (not sure it is
> >feasible)
> >      20 threads, each thread takes care of a socket server with a
> >different port.
> >   I want all socket servers start up and wait for client connection.
> >In the attached demo code, It stops at the startup of first socket
> >server somewhere in the following two lines and waits for client call:
> >
>
> Threads aren't the best way to manage the concurrency present in this
> application.  Instead, consider using non-blocking sockets with an
> event notification system.  For example, using Twisted, your program
> might look something like this:
>
> from twisted.internet import reactor, protocol, defer
>
> class CumulativeEchoProtocol(protocol.Protocol):
>     def connectionMade(self):
>         # Stop listening on the port which accepted this connection
>         self.factory.port.stopListening()
>
>         # Set up a list in which to collect the bytes which we receive
>         self.received = []
>
>
>     def connectionLost(self, reason):
>         # Notify the main program that this connection has been lost, so
>         # that it can exit the process when there are no more connections.
>         self.factory.onConnectionLost.callback(self)
>
>     def dataReceived(self, data):
>         # Accumulate the new data in our list
>         self.received.append(data)
>         # And then echo the entire list so far back to the client
>         self.transport.write(''.join(self.data))
>
> def allConnectionsLost():
>     # When all connections have been dropped, stop the reactor so the
>     # process can exit.
>     reactor.stop()
>
> def main():
>     # Set up a list to collect Deferreds in.  When all of these Deferreds
>     # have had callback() invoked on them, the reactor will be stopped.
>     completionDeferreds = []
>     for i in xrange(20):
>         # Make a new factory for this port
>         f = protocol.ServerFactory()
>
>         # Make a Deferred for this port's connection-lost event and make
>         # it available to the protocol by way of the factory.
>         d = defer.Deferred()
>         f.onConnectionLost = d
>         completionDeferreds.append(d)
>         f.protocol = CumulativeEchoProtocol
>
>         # Start listening on a particular port number with this factory
>         port = reactor.listenTCP(2000 + i + 1, f)
>
>         # Make the port object available to the protocol as well, so that
>         # it can be shut down when a connection is made.
>         f.port = port
>
>     # Create a Deferred which will only be called back when all the other
>     # Deferreds in this list have been called back.
>     d = defer.DeferredList(completionDeferreds)
>
>     # And tell it to stop the reactor when it fires
>     d.addCallback(lambda result: allConnectionsLost())
>
>     # Start the reactor so things can start happening
>     reactor.run()
>
> if __name__ == '__main__':
>     main()
> 
> Hope this helps,
> 
> Jean-Paul




More information about the Python-list mailing list