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 <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list