| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- .. include:: header.txt
- =======================
- Listeners and Clients
- =======================
- Usually message passing between processes is done using queues or by
- using connection objects returned by `Pipe()`.
- However, the `processing.connection` module allows some extra
- flexibility. It basically gives a high level API for dealing with
- sockets or Windows named pipes, and also has support for *digest
- authentication* using the `hmac` module from the standard library.
- Classes and functions
- =====================
- The module defines the following functions:
-
- `Listener(address=None, family=None, backlog=1, authenticate=False, authkey=None)`
- Returns a wrapper for a bound socket or Windows named pipe
- which is 'listening' for connections.
- `Client(address, family=None, authenticate=False, authkey=None)`
- Attempts to set up a connection to the listener which is using
- address `address`, returning a `connection object
- <connection-object.html>`_.
- The type of the connection is determined by `family`
- argument, but this can generally be omitted since it can
- usually be inferred from the format of `address`.
- If `authentication` or `authkey` is a string then digest
- authentication is used. The key used for authentication will
- be either `authkey` or `currentProcess.getAuthKey()` if
- `authkey` is `None`. If authentication fails then
- `AuthenticationError` is raised. See `Authentication keys`_.
- ..
- `deliverChallenge(connection, authkey)`
- Sends a randomly generated message to the other end of the
- connection and waits for a reply.
- If the reply matches the digest of the message using `authkey`
- as the key then a welcome message is sent to the other end of
- the connection. Otherwise `AuthenticationError` is raised.
- `answerChallenge(connection, authkey)`
- Receives a message, calculates the digest of the message using
- `authkey` as the key, and then sends the digest back.
- If a welcome message is not received then
- `AuthenticationError` is raised.
- The module exports two exception types:
- **exception** `AuthenticationError`
- Exception raised when there is an authentication error.
- **exception** `BufferTooShort`
- Exception raise by the `recvBytesInto()` method of a
- connection object when the supplied buffer object is too small
- for the message read.
- If `e` is an instance of `BufferTooShort` then `e.args[0]` will
- give the message as a byte string.
-
- Listener objects
- ================
- Instances of `Listener` have the following methods:
- `__init__(address=None, family=None, backlog=1, authenticate=False, authkey=None)`
- `address`
- The address to be used by the bound socket
- or named pipe of the listener object.
- `family`
- The type of the socket (or named pipe) to use.
- This can be one of the strings `'AF_INET'` (for a TCP
- socket), `'AF_UNIX'` (for a Unix domain socket) or
- `'AF_PIPE'` (for a Windows named pipe). Of these only
- the first is guaranteed to be available.
- If `family` is `None` than the family is inferred from the
- format of `address`. If `address` is also `None` then a
- default is chosen. This default is the family which is
- assumed to be the fastest available. See `Address
- formats`_.
-
- Note that if `family` is `'AF_UNIX'` then the associated
- file will have only be readable/writable by the user
- running the current process -- use `os.chmod()` is you need
- to let other users access the socket.
- `backlog`
- If the listener object uses a socket then `backlog` is
- passed to the `listen()` method of the socket once it has
- been bound.
- `authenticate`
- If `authenticate` is true or `authkey` is not `None` then
- digest authentication is used.
- `authkey`
- If `authkey` is a string then it will be used as the
- authentication key; otherwise it must be `None`.
- If `authkey` is `None` and `authenticate` is true then
- `currentProcess.getAuthKey()` is used as the authentication
- key.
- If `authkey` is `None` and `authentication` is false then
- no authentication is done.
- If authentication fails then `AuthenticationError` is
- raised. See `Authentication keys`_.
- `accept()`
- Accept a connection on the bound socket or named pipe of the
- listener object. If authentication is attempted and fails
- then `AuthenticationError` is raised.
- Returns a `connection object <connection-object.html>` object.
- `close()`
- Close the bound socket or named pipe of the listener object.
- This is called automatically when the listener is garbage
- collected. However it is advisable to call it explicitly.
- Listener objects have the following read-only properties:
- `address`
- The address which is being used by the listener object.
- `last_accepted`
- The address from which the last accepted connection came.
- If this is unavailable then `None` is returned.
- Address formats
- ===============
- * An `'AF_INET'` address is a tuple of the form `(hostname, port)`
- where `hostname` is a string and `port` is an integer
- * An `'AF_UNIX'` address is a string representing a filename on the
- filesystem.
- * An `'AF_PIPE'` address is a string of the form
- `r'\\\\.\\pipe\\PipeName'`.
-
- To use `Client` to connect to a named pipe on a remote computer
- called `ServerName` one should use an address of the form
- `r'\\\\ServerName\\pipe\\PipeName'` instead.
- Note that any string beginning with two backslashes is assumed by
- default to be an `'AF_PIPE'` address rather than an `'AF_UNIX'`
- address.
- Authentication keys
- ===================
- When one uses the `recv()` method of a connection object, the data
- received is automatically unpickled. Unfortunately unpickling data
- from an untrusted source is a security risk. Therefore `Listener` and
- `Client` use the `hmac` module to provide digest authentication.
- An authentication key is a string which can be thought of as a
- password: once a connection is established both ends will demand proof
- that the other knows the authentication key. (Demonstrating that both
- ends are using the same key does *not* involve sending the key over
- the connection.)
- If authentication is requested but do authentication key is specified
- then the return value of `currentProcess().getAuthKey()` is used (see
- `Process objects <process-objects.html>`_). This value will
- automatically inherited by any `Process` object that the current
- process creates. This means that (by default) all processes of a
- multi-process program will share a single authentication key which can
- be used when setting up connections between the themselves.
- Suitable authentication keys can also be generated by using
- `os.urandom()`.
- Example
- =======
- The following server code creates a listener which uses `'secret
- password'` as an authentication key. It then waits for a connection
- and sends some data to the client::
- from processing.connection import Listener
- from array import array
- address = ('localhost', 6000) # family is deduced to be 'AF_INET'
- listener = Listener(address, authkey='secret password')
- conn = listener.accept()
- print 'connection accepted from', listener.last_accepted
- conn.send([2.25, None, 'junk', float])
- conn.sendBytes('hello')
- conn.sendBytes(array('i', [42, 1729]))
- conn.close()
- listener.close()
- The following code connects to the server and receives some data from
- the server::
- from processing.connection import Client
- from array import array
- address = ('localhost', 6000)
- conn = Client(address, authkey='secret password')
- print conn.recv() # => [2.25, None, 'junk', float]
- print conn.recvBytes() # => 'hello'
- arr = array('i', [0, 0, 0, 0, 0])
- print conn.recvBytesInto(arr) # => 8
- print arr # => array('i', [42, 1729, 0, 0, 0])
- conn.close()
- .. _Prev: sharedctypes.html
- .. _Up: processing-ref.html
- .. _Next: programming-guidelines.html
|