Python의 xmlrpc 모듈과 관련하여 Pickle-RPC를 구현했습니다.RPC를 통해 등록 정보에 액세스하는 방법
클라이언트 측에서 RPC 서버에 등록 된 인스턴스의 메서드를 호출 할 수 있습니다.
s = ServerProxy(('127.0.0.1', 49152), DatagramRequestSender)
s.foo('bar')
속성에 액세스하고 싶습니다.
s = ServerProxy(('127.0.0.1', 49152), DatagramRequestSender)
s.foobar
어떻게 구현해야합니까?
client.py
import pickle
import socket
from io import BytesIO
class StreamRequestSender:
max_packet_size = 8192
address_family = socket.AF_INET
socket_type = socket.SOCK_STREAM
def send_request(self, address, request):
with socket.socket(self.address_family, self.socket_type) as client_socket:
with client_socket.makefile('wb') as wfile:
pickle.dump(request, wfile)
with client_socket.makefile('rb') as rfile:
response = pickle.load(rfile)
return response
class DatagramRequestSender(StreamRequestSender):
socket_type = socket.SOCK_DGRAM
def send_request(self, address, request):
with socket.socket(self.address_family, self.socket_type) as client_socket:
with BytesIO() as wfile:
pickle.dump(request, wfile)
client_socket.sendto(wfile.getvalue(), address)
data = client_socket.recv(self.max_packet_size)
with BytesIO(data) as rfile:
response = pickle.load(rfile)
return response
class ServerProxy:
def __init__(self, address, RequestSenderClass):
self.__address = address
self.__request_sender = RequestSenderClass()
def __send(self, method, args):
request = (method, args)
response = self.__request_sender.send_request(self.__address, request)
return response
def __getattr__(self, name):
return _Method(self.__send, name)
class _Method:
def __init__(self, send, name):
self.__send = send
self.__name = name
def __getattr__(self, name):
return _Method(self.__send, "{}.{}".format(self.__name, name))
def __call__(self, *args):
return self.__send(self.__name, args)
if __name__ == '__main__':
s = ServerProxy(('127.0.0.1', 49152), DatagramRequestSender)
print(s.pow(2, 160))
server.py
import pickle
import sys
from socketserver import StreamRequestHandler, DatagramRequestHandler, ThreadingTCPServer, ThreadingUDPServer
class RPCRequestHandler:
def handle(self):
method, args = pickle.load(self.rfile)
response = self.server.dispatch(method, args)
pickle.dump(response, self.wfile)
class StreamRPCRequestHandler(RPCRequestHandler, StreamRequestHandler):
pass
class DatagramRPCRequestHandler(RPCRequestHandler, DatagramRequestHandler):
pass
class RPCDispatcher:
def __init__(self, instance=None):
self.__instance = instance
def register_instance(self, instance):
self.__instance = instance
def dispatch(self, method, args):
_method = None
if self.__instance is not None:
try:
_method = self._resolve_dotted_attribute(self.__instance, method)
except AttributeError:
pass
if _method is not None:
return _method(*args)
else:
raise Exception('method "{}" is not supported'.format(method))
@staticmethod
def _resolve_dotted_attribute(obj, dotted_attribute):
attributes = dotted_attribute.split('.')
for attribute in attributes:
if attribute.startswith('_'):
raise AttributeError('attempt to access private attribute "{}"'.format(attribute))
else:
obj = getattr(obj, attribute)
return obj
class RPCServer(ThreadingUDPServer, RPCDispatcher):
def __init__(self, server_address, RPCRequestHandlerClass, instance=None):
ThreadingUDPServer.__init__(self, server_address, RPCRequestHandlerClass)
RPCDispatcher.__init__(self, instance)
if __name__ == '__main__':
class ExampleService:
def pow(self, base, exp):
return base ** exp
s = RPCServer(('127.0.0.1', 49152), DatagramRPCRequestHandler, ExampleService())
print('Serving Pickle-RPC on localhost port 49152')
print('It is advisable to run this example server within a secure, closed network.')
try:
s.serve_forever()
except KeyboardInterrupt:
print("\nKeyboard interrupt received, exiting.")
s.server_close()
sys.exit(0)
Pyro4의'Proxy' 클래스는 올바르게 이해하면 동적으로 관리되는'_pyroAttrs'를 사용하여 원격 속성을받습니다. 우리는 의사 소통없이 동적으로 방법/속성을 단호히 해결할 수는 없습니까? 추신 Pyro4는 아주 멋진 라이브러리입니다. 나는 무엇인가 묻고 싶다. 그 중 하나 인 Pyro 4는 TCP와 UDP의 차이를 어떻게 흡수합니까? 고맙습니다. – sira
질문을 이해할 수 없습니다. Pyro4는 TCP/IP 소켓을 독점적으로 사용하기 때문에, Pyro가 UDP를 통해 신뢰할 수있는 RPC를 수행 할 수있는 방법은 없습니다 (이는 패킷의 순서를 보장하지 못하는 신뢰할 수없는 프로토콜입니다). 이 문제를 논의 할 곳 : –
아, 알겠습니다. 고맙습니다. – sira