Distributed programming: Difference between revisions

→‎Socket, Plain Text: changed the code to make it satisfy the task description
No edit summary
(→‎Socket, Plain Text: changed the code to make it satisfy the task description)
Line 974:
print 'Server Message: %s' % response.read()</lang>
 
===Socket, PlainPickle Textformat===
{{incomplete|Python}}
'''Protocol:''' Plain Text
 
'''Protocol:''' raw socket / pickle format
Use with Pythons [http://docs.python.org/library/pickle.html#module-pickle pickle module] for data serialization into printable text would allow the transfer of arbitrary Python data, but as it stands, this method is too low level to fulfill the task.
 
This example builds a very basic RPC mechanism on top of sockets and the [http://docs.python.org/library/pickle.html#module-pickle pickle module]. Please note that the pickle module is not secure - a malicious client can build malformed data to execute arbitrary code on the server. If untrusted clients can access the server, the [http://docs.python.org/library/json.html json module] could be used as a substitute, but we lose the ability to transfer arbitrary Python objects that way.
 
==== Server ====
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import SocketServer
import pickle
 
HOST = "localhost"
PORT = 8000
 
class RPCServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
# our instance that will upper whatever it gets and send back to client
# The object_to_proxy member should be set to the object we want
class UpperCaseHandler(SocketServer.StreamRequestHandler):
# methods called on. Unfortunately, we can't do this in the constructor
# because the constructor should not be overridden in TCPServer...
 
daemon_threads = True
 
class RPCHandler(SocketServer.StreamRequestHandler):
def handle(self):
in_channel = pickle.Unpickler(self.rfile)
print '%s connected' % self.client_address[0]
out_channel = pickle.Pickler(self.wfile, protocol=2)
# get what client sends
getwhile = self.rfile.readline()True:
# write back to clienttry:
name, args, kwargs = in_channel.load()
self.wfile.write(get.upper())
print 'got %s %s %s' % (name, args, kwargs)
except EOFError:
# EOF means we're done with this request.
# Catching this exception to detect EOF is a bit hackish,
# but will work for a quick demo like this
break
try:
method = getattr(self.server.object_to_proxy, name)
result = method(*args, **kwargs)
except Exception, e:
out_channel.dump(('Error',e))
else:
out_channel.dump(('OK',result))
 
class MyHandlerInstance(object):
def echo(self, data):
'''Method for returning data got from client'''
return 'Server responded: %s' % data
def div(self, dividend, divisor):
'''Method to divide 2 numbers'''
return dividend/divisor
def is_computer_on(self):
return True
if __name__ == '__main__':
tcpserverrpcserver = SocketServer.TCPServerRPCServer((HOST, PORT), UpperCaseHandlerRPCHandler)
rpcserver.object_to_proxy = MyHandlerInstance()
try:
tcpserverrpcserver.serve_forever()
except KeyboardInterrupt:
print 'Exiting...'
tcpserverrpcserver.server_close()</lang>
</lang>
 
==== Client ====
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import socket
import pickle
 
HOST = "localhost"
PORT = 8000
 
class RPCClient(object):
DATA = "my name is eren"
def __init__(self, host, port):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.connect((host, port))
self.rfile = self.socket.makefile('rb')
self.wfile = self.socket.makefile('wb')
self.in_channel = pickle.Unpickler(self.rfile)
self.out_channel = pickle.Pickler(self.wfile, protocol=2)
 
def _close(self):
# connect to server and send data
self.socket.close()
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.rfile.close()
sock.connect((HOST, PORT))
self.wfile.close()
sock.send("%s\n" % DATA)
 
# Make calling remote methods easy by overriding attribute access.
# get
# Accessing any attribute on our instances will give a proxy method that
response = sock.recv(256)
# calls the method with the same name on the remote machine.
sock.close()
def __getattr__(self, name):
def proxy(*args, **kwargs):
self.out_channel.dump((name, args, kwargs))
self.wfile.flush() # to make sure the server won't wait forever
status, result = self.in_channel.load()
if status == 'OK':
return result
else:
raise result
 
return proxy
if __name__ == '__main__':
# connect to server and send data
rpcclient = RPCClient(HOST, PORT)
 
print 'Testing the echo() method:'
print "We sent: %s" % DATA
print rpcclient.echo('Hello world!')
print 'Server responded: %s' % response</lang>
print
print 'Calculating 42/2 on the remote machine:'
print rpcclient.div(42, 2)
print
print 'is_computer_on on the remote machine returns:'
print rpcclient.is_computer_on()
print
print 'Testing keyword args:'
print '42/2 is:', rpcclient.div(divisor=2, dividend=42)
rpcclient._close()
del rpcclient</lang>
 
===Pyro===
Anonymous user