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