2008-11-11 4 views
4

Я создаю программу, которая имеет класс, используемый локально, но я хочу, чтобы один и тот же класс использовался таким же образом по сети. Это означает, что мне нужно иметь возможность делать синхронные вызовы любому из своих общедоступных методов. Класс читает и записывает файлы, поэтому я считаю, что XML-RPC слишком накладные. Я создал базовый клиент/сервер rpc, используя примеры из скрученного, но у меня возникают проблемы с клиентом.Как выполнять синхронные вызовы rpc

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

Это работает для одного вызова, когда данные получил я звоню reactor.stop(), но если я сделаю больше звонков реактор не будет перезагружен. Есть ли что-то еще, что я должен использовать для этого? может быть, другой витой модуль или другая структура?

(я не в том числе сведения о том, как работает протокол, потому что главное, что я получаю только один вызов из этого.)

Добавление & Разъяснение:

Я поделился Google doc с заметками о том, что я делаю. http://docs.google.com/Doc?id=ddv9rsfd_37ftshgpgz

У меня есть версия, которая использует плавкий предохранитель и может объединять несколько локальных папок в точке крепления плавкого предохранителя. Доступ к файлу уже обрабатывается внутри класса, поэтому я хочу иметь серверы, которые дают мне доступ к сети одному классу. После продолжения поиска я подозреваю, что pyro (http://pyro.sourceforge.net/) может быть тем, что я действительно ищу (просто на основе чтения их домашней страницы прямо сейчас), но я открыт для любых предложений.

Я мог бы добиться аналогичных результатов с помощью монтирования nfs и комбинирования его с моей локальной папкой, но я хочу, чтобы все одноранговые узлы имели доступ к одной и той же объединенной файловой системе, так что каждый компьютер должен был петь nfs-сервер с количество монтируемых nfs равно числу компьютеров в сети.

Вывод: Я решил использовать rpyc, поскольку он дал мне именно то, что я искал. Сервер, который хранит экземпляр класса, который я могу манипулировать, как если бы он был локальным. Если кому-то интересно, я поставил свой проект на Launchpad (http://launchpad.net/dstorage).

ответ

2

Если вы даже рассматриваете Pyro, сначала проверьте RPyC и передумайте XML-RPC.

Что касается витой резины, попробуйте оставить реактор вместо того, чтобы останавливать его, и только ClientCreator(...).connectTCP(...) каждый раз.

Если у вас self.transport.loseConnection() в вашем Протоколе вы не оставите открытые соединения.

1

Для синхронного клиента Twisted, вероятно, не является подходящим вариантом. Вместо этого вы можете напрямую использовать модуль сокета.

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() 

recv() вызова, возможно, потребуется повторить, пока вы не получите пустую строку, но это показывает основу.

В качестве альтернативы, вы можете изменить всю вашу программу для поддержки асинхронных вызовов ...

1

Если вы используете Twisted вероятно, вы должны знать, что:

  1. Вы не будете делать синхронные вызовы в любой сети обслуживание
  2. Реактор может работать только один раз, поэтому не останавливайте его (позвонив reactor.stop()), пока ваше приложение не будет готово к выходу.

Надеюсь, это ответит на ваш вопрос. Я лично считаю, что Twisted точно - правильное решение для вашего прецедента, но вам нужно обойти проблему синхронности.

Добавление & Разъяснение:

Часть того, что я не понимаю, , что, когда я называю reactor.run() это , кажется, идет в петлю, что только часы для сетевой активности. Как мне продолжить работу с остальной частью моей программы , пока она использует сеть? if Я могу пройти мимо этого, тогда я могу , вероятно, работать через проблему синхронности .

Это как раз, что реактор.run(). Он управляет основным контуром, который является реактором событий. Он будет не только ждать событий, связанных с работой, но и всего, что вы запланировали. С Twisted вам нужно будет структурировать остальную часть вашего приложения, чтобы справиться с его асинхронным характером. Возможно, если бы мы знали, что это за приложение, мы могли бы посоветовать.

+0

Под «не останавливайтесь», вы имеете в виду, не называйте jet.stop()? – 2008-11-11 22:23:03

+0

Часть того, что я не понимаю, заключается в том, что когда я вызываю реактор.run(), похоже, он переходит в цикл, который просто следит за сетевой активностью. Как продолжить работу с остальной частью моей программы, когда она использует сеть? если я смогу пройти мимо этого, то я, вероятно, смогу решить проблему синхронности. – 2008-11-11 22:23:54

2

Почему вы считаете, что это должно быть синхронно?

Если вы хотите, чтобы только одно из них происходило за один раз, вызовите все вызовы через DeferredSemaphore, чтобы вы могли ограничить фактические вызовы (любым произвольным значением).

Если вы хотите иметь возможность запускать несколько потоков из них в разное время, но не заботятся о ограничениях параллелизма, тогда вы должны по крайней мере разделить запуск и отключение реактора от вызовов (реактор должен работать в течение всего время жизни процесса).

Если вы просто не можете понять, как выразить логику вашего приложения в шаблоне реактора, вы можете использовать deferToThread и написать кусок чисто синхронного кода, хотя я бы предположил, что это не понадобится.

Смежные вопросы