Thanks John.<br><br>Here is some sample code that is somewhat working for me right now.  Any and all comments are greatly appreciated.<br><br>1) I setup a netcat listener on port 8080.<br>2) Start the twisted program, it connects to 8080 and then fires up a listener on port 808 from the <span style="font-family: courier new,monospace;">ChattyMCProtocol</span> protocol.<br>
3) Start a netcat client connection to the server process.<br>4) The client connection and any data they enter will be passed to the &#39;master control&#39; process (ReconnectingClientFactory).<br><br><span style="font-family: courier new,monospace;">from twisted.internet.protocol import ReconnectingClientFactory, ServerFactory</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">from twisted.protocols.basic import LineOnlyReceiver</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">from twisted.internet import reactor</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">&quot;&quot;&quot;Some test code using a chat-like approach with a master control node&quot;&quot;&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">class ChattyServerProtocol(LineOnlyReceiver):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    &#39;&#39;&#39;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    A test proto which will receive data and then forward it on the to the master control</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    &#39;&#39;&#39;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    delimiter = &#39;\n&#39;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def connectionMade(self):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        self.transport.write(&quot;Welcome to the Server\n&quot;)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        &quot;&quot;&quot; Tell the master control that a client came in&quot;&quot;&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        self.factory.parent.transport.write(&quot;Someone connected\n&quot;)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">                </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    def connectionLost(self, reason):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        self.factory.parent.transport.write(&quot;Server lost the connection to a client&quot;)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def lineReceived(self, line):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        print &quot;Server got some data: &quot; + line</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        &quot;&quot;&quot; Now send the data to the master control&quot;&quot;&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        self.factory.parent.transport.write(&quot;Client Said: %s\n&quot; % line)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">class ChattyServerFactory(ServerFactory):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    protocol = ChattyServerProtocol</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def __init__(self, parent):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        self.parent = parent</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        pass</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">class ChattyMCProtocol(LineOnlyReceiver):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    delimiter = &#39;\n&#39;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def __init__(self):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        &quot;&quot;&quot;Connected so startup Server for clients&quot;&quot;&quot;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        self.server_factory = ChattyServerFactory(self)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        reactor.listenTCP(808, self.server_factory)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    def lineReceived(self, line):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        self.transport.write(&quot;Processing what you said: %s\n&quot; % line)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">                </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">class ChattyMCFactory(ReconnectingClientFactory):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">     </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    def startedConnecting(self, connector):</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        print &quot;Connecting...&quot;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    def clientConnectionFailed(self, connector, reason):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        print &quot;The connection failed&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    def clientConnectionLost(self, connector, reason):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        print &quot;The connection was lost&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    def buildProtocol(self, addr):</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        print &quot;Connected, reset the delay&quot;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        self.resetDelay()</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        # Next startup a server for the clients</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">        #self.server_factory = ChattyServerFactory(self)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">        return ChattyMCProtocol()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">reactor.connectTCP(&quot;127.0.0.1&quot;, 8080, ChattyMCFactory())</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">reactor.run()</span><br>        <br>Items that I don&#39;t know how to handle yet:<br> - I need to determine how to better handle the case where the connection made via ReconnectingClientFactory is dropped.  It does reconnect as the Factory should but the problem is that the Server portion is not cleanly shutdown so when the ChattyMCProtocol tries to listen it fails as the socket is already in use.  Any ideas how to signal to the server to shutdown?<br>
 - Much more to be done.  How to take this to the level of a proper Twisted &quot;application&quot;, etc.<br><br>Thanks,<br>-ab<br><br><div class="gmail_quote">On Thu, May 28, 2009 at 12:01 PM, John Santos <span dir="ltr">&lt;<a href="mailto:JOHN@egh.com">JOHN@egh.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><br>
Hi Adam -<br>
<br>
I&#39;m in pretty much the same situation as you and am working on a similar<br>
problem.  Very much a Python and Twisted newbie.<br>
<br>
The program I&#39;m working on needs to talk to a variety of clients and to<br>
a single server, with more-or-less permanent connections to all of them.<br>
<br>
My problem is somewhat different from yours (and probably a little<br>
simpler), since all input from all clients goes to the server, and<br>
all output from the server goes to all clients (so I don&#39;t have to<br>
tag and remember which response goes to which client.)  However,<br>
there are other messages from the clients that don&#39;t go to the<br>
server, but instead do other things, some requiring responses.<br>
So the message handling in my program (what happens when dataRecieved<br>
gets called) may be more complicated than in yours.  But that is<br>
(at least from my perspective) the easy part.  Getting the twisted<br>
app to talk to the server and all the clients, and not to fall over<br>
dead when a client goes away, etc. is (to me) the hard part, and I<br>
feel like I&#39;ve just gotten over a huge hump now that that is (mostly)<br>
working (as of two days ago.)<br>
<br>
<br>
I am using two factories, one to generate the object that talks to the<br>
server (using conch.telnet), and one to generate objects to talk to<br>
the clients.  The clients can come and go but would typically be<br>
permanent.  (Actually 3 factories right now, since I&#39;m using the<br>
StdioProxyFactory from the example for debugging, but that will<br>
go away as I get the client protocol working.)<br>
<br>
I started from the dataforward.py example in Twisted book, but by<br>
now it has been massively changed.<br>
<br>
Before starting the reactor, I do a reactor.connectTCP to the server<br>
using the factory for the server connections and a reactor.listenTCP<br>
using the client connection factory, to listen for client connections.<br>
<br>
One change I had to make to the example was to promote the<br>
InputForwarder object from an attribute of the client connection<br>
object to a global object since it is common to all the<br>
client connections.  (I hope I have the terminology correct here;<br>
as I&#39;ve said, I&#39;m a Python newbie.)<br>
<br>
It turns out to be fairly small amount of code, and I think it<br>
can still be simplified some more.<br>
<br>
So I think you are on the right track.  HTH!<br>
<font color="#888888"><br>
<br>
--<br>
John Santos<br>
Evans Griffiths &amp; Hart, Inc.<br>
781-861-0670 ext 539</font><br></blockquote></div><br>