# RPCUDP : [RPC](http://en.wikipedia.org/wiki/Remote_procedure_call) over [UDP](http://en.wikipedia.org/wiki/User_Datagram_Protocol) in Python
RPC over UDP may seem like a silly idea, but things like the [DHT](http://en.wikipedia.org/wiki/Distributed_hash_table) [Kademlia](http://en.wikipedia.org/wiki/Kademlia) require it. This project is specifically designed for asynchronous [Python Twisted](http://twistedmatrix.com) code to accept and send remote proceedure calls.
Because of the use of UDP, you will not always know whether or not a procedure call was successfully received. This isn't considered an exception state in the library, though you will know if a response isn't received by the server in a configurable amount of time.
## Installation
```
pip install storjrpcudp
```
## Usage
*This assumes you have a working familiarity with Twisted.*
First, let's make a server that accepts a remote procedure call and spin it up.
```python
from rpcudp.protocol import RPCProtocol
from twisted.internet import reactor
class RPCServer(RPCProtocol):
# Any methods starting with "rpc_" are available to clients.
def rpc_sayhi(self, sender, name):
# This could return a Deferred as well. sender is (ip,port)
return "Hello %s you live at %s:%i" % (name, sender[0], sender[1])
# start a server on UDP port 1234
reactor.listenUDP(1234, RPCServer())
reactor.run()
```
Now, let's make a client. Note that we do need to specify a port for the client as well, since it needs to listen for responses to RPC calls on a UDP port.
```python
from rpcudp.protocol import RPCProtocol
from twisted.internet import reactor
class RPCClient(RPCProtocol):
def handleResult(self, result):
# result will be a tuple - first arg is a boolean indicating whether a response
# was received, and the second argument is the response if one was received.
if result[0]:
print "Success! %s" % result[1]
else:
print "Response not received."
client = RPCClient()
reactor.listenUDP(5678, client)
client.sayhi(('127.0.0.1', 1234), "Snake Plissken").addCallback(client.handleResult)
reactor.run()
```
You can run this example in the example.py file in the root folder.
## Implementation Details
The protocol is designed to be as small and fast as possible. Python objects are serialized using [MsgPack](http://msgpack.org/). All calls must fit within 8K (generally small enough to fit in one datagram packet).
## Compatibility
With version 2.0 compatibility is broken with previous versions. In version 2.0 the method name when making a remote call is always packed as a unicode string. In previous versions, the type of string that method name was depended on the Python version. In order to make instances running on Python 2 and Python 3 compatible with each other the method name is now encoded as a unicode string before being packed, which ensures that [u-msgpack-python](https://github.com/vsergeev/u-msgpack-python) will always pack the it the same way. See [u-msgpack-python#behaviour-notes](https://github.com/vsergeev/u-msgpack-python#behavior-notes) for more information.
If you intend to have instances running on both Python 2 and Python 3 communicating with each other make sure that all strings in the arguments you send are unicode encoded as well to ensure compatibility.
RPC over UDP may seem like a silly idea, but things like the [DHT](http://en.wikipedia.org/wiki/Distributed_hash_table) [Kademlia](http://en.wikipedia.org/wiki/Kademlia) require it. This project is specifically designed for asynchronous [Python Twisted](http://twistedmatrix.com) code to accept and send remote proceedure calls.
Because of the use of UDP, you will not always know whether or not a procedure call was successfully received. This isn't considered an exception state in the library, though you will know if a response isn't received by the server in a configurable amount of time.
## Installation
```
pip install storjrpcudp
```
## Usage
*This assumes you have a working familiarity with Twisted.*
First, let's make a server that accepts a remote procedure call and spin it up.
```python
from rpcudp.protocol import RPCProtocol
from twisted.internet import reactor
class RPCServer(RPCProtocol):
# Any methods starting with "rpc_" are available to clients.
def rpc_sayhi(self, sender, name):
# This could return a Deferred as well. sender is (ip,port)
return "Hello %s you live at %s:%i" % (name, sender[0], sender[1])
# start a server on UDP port 1234
reactor.listenUDP(1234, RPCServer())
reactor.run()
```
Now, let's make a client. Note that we do need to specify a port for the client as well, since it needs to listen for responses to RPC calls on a UDP port.
```python
from rpcudp.protocol import RPCProtocol
from twisted.internet import reactor
class RPCClient(RPCProtocol):
def handleResult(self, result):
# result will be a tuple - first arg is a boolean indicating whether a response
# was received, and the second argument is the response if one was received.
if result[0]:
print "Success! %s" % result[1]
else:
print "Response not received."
client = RPCClient()
reactor.listenUDP(5678, client)
client.sayhi(('127.0.0.1', 1234), "Snake Plissken").addCallback(client.handleResult)
reactor.run()
```
You can run this example in the example.py file in the root folder.
## Implementation Details
The protocol is designed to be as small and fast as possible. Python objects are serialized using [MsgPack](http://msgpack.org/). All calls must fit within 8K (generally small enough to fit in one datagram packet).
## Compatibility
With version 2.0 compatibility is broken with previous versions. In version 2.0 the method name when making a remote call is always packed as a unicode string. In previous versions, the type of string that method name was depended on the Python version. In order to make instances running on Python 2 and Python 3 compatible with each other the method name is now encoded as a unicode string before being packed, which ensures that [u-msgpack-python](https://github.com/vsergeev/u-msgpack-python) will always pack the it the same way. See [u-msgpack-python#behaviour-notes](https://github.com/vsergeev/u-msgpack-python#behavior-notes) for more information.
If you intend to have instances running on both Python 2 and Python 3 communicating with each other make sure that all strings in the arguments you send are unicode encoded as well to ensure compatibility.
Metadata
Release files for storjrpcudp 2.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| storjrpcudp-2.5.tar.gz | 4.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| storjrpcudp-2.5-py2.py3-none-any.whl | Python 2, Python 3 | none | any | Details |
Total release size: 12.9 kB
Release files / storjrpcudp-2.5.tar.gz
| Download URL | storjrpcudp-2.5.tar.gz |
|---|---|
| Size | 4.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2bbb0864795783ece1d4134f7b2f3e1d3725b063a94cb6cf129667fe4db13ec1
|
|
BLAKE2b-256 checksum How to use checksums |
5d2471391214910416ac5debc72d0cb905a6e9d7582497c06761bb25ded9c7fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
Release files / storjrpcudp-2.5-py2.py3-none-any.whl
| Download URL | storjrpcudp-2.5-py2.py3-none-any.whl |
|---|---|
| Size | 8.8 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
a14241a528b32d0d4378230d5a1475a628e4294865e056bbc4b127fe14029ae4
|
|
BLAKE2b-256 checksum How to use checksums |
f72b8332c4e9763143766343fa9d20ab91e7a0d41b2fa5510d16dee31bbc8576
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |