tags:

views:

734

answers:

4

I'm building a program that has a class used locally, but I want the same class to be used the same way over the network. This means I need to be able to make synchronous calls to any of its public methods. The class reads and writes files, so I think XML-RPC is too much overhead. I created a basic rpc client/server using the examples from twisted, but I'm having trouble with the client.

c = ClientCreator(reactor, Greeter)
c.connectTCP(self.host, self.port).addCallback(request)
reactor.run()

This works for a single call, when the data is received I'm calling reactor.stop(), but if I make any more calls the reactor won't restart. Is there something else I should be using for this? maybe a different twisted module or another framework?

(I'm not including the details of how the protocol works, because the main point is that I only get one call out of this.)

Addendum & Clarification:

I shared a google doc with notes on what I'm doing. http://docs.google.com/Doc?id=ddv9rsfd_37ftshgpgz

I have a version written that uses fuse and can combine multiple local folders into the fuse mount point. The file access is already handled within a class, so I want to have servers that give me network access to the same class. After continuing to search, I suspect pyro (http://pyro.sourceforge.net/) might be what I'm really looking for (simply based on reading their home page right now) but I'm open to any suggestions.

I could achieve similar results by using an nfs mount and combining it with my local folder, but I want all of the peers to have access to the same combined filesystem, so that would require every computer to bee an nfs server with a number of nfs mounts equal to the number of computers in the network.

Conclusion: I have decided to use rpyc as it gave me exactly what I was looking for. A server that keeps an instance of a class that I can manipulate as if it was local. If anyone is interested I put my project up on Launchpad (http://launchpad.net/dstorage).

A: 

For a synchronous client, Twisted probably isn't the right option. Instead, you might want to use the socket module directly.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((self.host, self.port))
s.send(output)
data = s.recv(size)
s.close()

The recv() call might need to be repeated until you get an empty string, but this shows the basics.

Alternatively, you can rearrange your entire program to support asynchronous calls...

eswald
+1  A: 

If you are using Twisted you should probably know that:

  1. You will not be making synchronous calls to any network service
  2. The reactor can only ever be run once, so do not stop it (by calling reactor.stop()) until your application is ready to exit.

I hope this answers your question. I personally believe that Twisted is exactly the correct solution for your use case, but that you need to work around your synchronicity issue.

Addendum & Clarification:

Part of what I don't understand is that when I call reactor.run() it seems to go into a loop that just watches for network activity. How do I continue running the rest of my program while it uses the network? if I can get past that, then I can probably work through the synchronicity issue.

That is exactly what reactor.run() does. It runs a main loop which is an event reactor. It will not only wait for entwork events, but anything else you have scheduled to happen. With Twisted you will need to structure the rest of your application in a way to deal with its asynchronous nature. Perhaps if we knew what kind of application it is, we could advise.

Ali A
By "do not stop", you mean do not call reactor.stop()?
S.Lott
Part of what I don't understand is that when I call reactor.run() it seems to go into a loop that just watches for network activity. How do I continue running the rest of my program while it uses the network? if I can get past that, then I can probably work through the synchronicity issue.
Asa Ayers
S. Lott, yes, have updated the content.Asa-ayers, I have updated the content to reflect your comment.
Ali A
I updated my question to supply more information on what I'm actually building.
Asa Ayers
+2  A: 

If you're even considering Pyro, check out RPyC first, and re-consider XML-RPC.

Regarding Twisted: try leaving the reactor up instead of stopping it, and just ClientCreator(...).connectTCP(...) each time.

If you self.transport.loseConnection() in your Protocol you won't be leaving open connections.

orip
+2  A: 

Why do you feel that it needs to be synchronous?

If you want to ensure that only one of these is happening at a time, invoke all of the calls through a DeferredSemaphore so you can rate limit the actual invocations (to any arbitrary value).

If you want to be able to run multiple streams of these at different times, but don't care about concurrency limits, then you should at least separate reactor startup and teardown from the invocations (the reactor should run throughout the entire lifetime of the process).

If you just can't figure out how to express your application's logic in a reactor pattern, you can use deferToThread and write a chunk of purely synchronous code -- although I would guess this would not be necessary.

Dustin
The reason I wanted it to be synchronous is that I have a class that functions locally, and I just need network access an instance of the same class running on another computer. It needs to work exactly the same way with the same functions. I'm using rpyc and its working very well.
Asa Ayers