Commit 5034eae4 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Documentation

parent b4bd4350
**twspy** is a standalone implementation of web sockets for Python, defined by
[RFC 6455](http://tools.ietf.org/html/rfc6455).
About
=====
- The `websocket` class upgrades a regular socket to a web socket. A websocket
instance is a single end point of a connection. A `websocket` instance sends
and receives frames (`Frame` instances) as opposed to bytes (which are
sent/received in a regular socket).
*twspy* is a standalone implementation of web sockets for Python, defined by
[RFC 6455](http://tools.ietf.org/html/rfc6455). The incentive for creating this
library is the absence of a layered implementation of web sockets outside the
scope of web servers such as Apache or Nginx. *twspy* does not require any
third-party programs or libraries outside Python's standard library. It
provides low-level access to sockets, as well as high-level functionalities to
easily set up a web server. Thus, it is both suited for quick server
programming, as well as for more demanding applications that require low-level
control over each frame being sent/received.
Her is a quick overview of the features in this library:
- Upgrading regular sockets to web sockets.
- Building custom frames.
- Messages, which are higher-level than frames (see "Basic usage").
- Connections, which hide the handling of control frames and automatically
concatenate fragmented messages to individual payloads.
- HTTP authentication during handshake.
- An extendible server implementation.
- Secure sockets using SSL certificates (for 'wss://...' URL's).
- The possibility to add extensions to the web socket protocol. An included
implementation is [deflate-frame](http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06).
Basic usage
===========
- The `websocket` class upgrades a regular socket to a web socket. A
`websocket` instance is a single end point of a connection. A `websocket`
instance sends and receives frames (`Frame` instances) as opposed to bytes
(which are sent/received in a regular socket).
Server example:
import twspy, socket
sock = twspy.websocket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('', 8000))
sock.listen()
client = sock.accept()
client.send(twspy.Frame(twspy.OPCODE_TEXT, 'Hello, Client!'))
frame = client.recv()
Client example:
import twspy
sock = twspy.websocket(location='/my/path')
sock.connect(('', 8000))
sock.send(twspy.Frame(twspy.OPCODE_TEXT, 'Hello, Server!'))
- A `Connection` instance represents a connection between two end points, based
on a `websocket` instance. A connection handles control frames properly, and
......@@ -12,3 +57,80 @@
frames). Messages are automatically converted to frames, and received frames
are converted to messages. Fragmented messages (messages consisting of
multiple frames) are also supported.
Example of an echo server (sends back what it receives):
import twspy
class EchoConnection(twspy.Connection):
def onopen(self):
print 'Connection opened at %s:%d' % self.sock.getpeername()
def onmessage(self, message):
print 'Received message "%s"' % message.payload
self.send(twspy.TextMessage(message.payload))
def onclose(self, message):
print 'Connection closed'
server = twspy.websocket()
server.bind(('', 8000))
server.listen()
while True:
client, addr = server.accept()
EchoConnection(client).receive_forever()
There are two types of messages: `TextMessage`s and `BinaryMessage`s. A
`TextMessage` uses frames with opcode `OPCODE_TEXT`, and encodes its payload
using UTF-8 encoding. A `BinaryMessage` just sends its payload as raw data.
I recommend using `TextMessage` by default, and `BinaryMessage` only when
necessary.
**Note:** For browser clients, you will probably want to use JSON encoding.
This could, for example, be implemented as follows:
import twspy, json
def msg(**data):
return twspy.TextMessage(json.dumps(data))
# create some connection `conn`...
conn.send(msg(foo='Hello, World!'))
- The built-in `Server` implementation is very basic. It starts a new thread
with a `Connection.receive_forever()` loop for each client that connects. It
also handles client crashes properly. By default, a `Server` instance only
logs every event using Python's `logging` module. To create a custom server,
The `Server` class should be extended and its event handlers overwritten. The
event handlers are named identically to the `Connection` event handlers, but
they also receive an additional `client` argument. This argument is a
modified `Connection` instance, so you can invoke `send()` and `recv()`.
For example, the `EchoConnection` example above can be rewritten to:
import twspy
class EchoServer(twspy.Server):
def onopen(self, client):
print 'Client %s connected' % client
def onmessage(self, client, message):
print 'Received message "%s"' % message.payload
client.send(twspy.TextMessage(message.payload))
def onclose(self, client):
print 'Client %s disconnected' % client
EchoServer(8000).run()
The server can be stopped by typing CTRL-C in the command line. The
`KeyboardInterrupt` raised when this happens is caught by the server.
Extensions
==========
TODO
......@@ -9,12 +9,34 @@ from errors import SocketClosed, PingError
class Connection(object):
"""
A Connection uses a websocket instance to send and receive (optionally
fragmented) messages, which are Message instances. Control frames are
A `Connection` uses a `websocket` instance to send and receive (optionally
fragmented) messages, which are `Message` instances. Control frames are
handled automatically in the way specified by RFC 6455.
To use the Connection class, it should be extended and the extending class
should implement the on*() event handlers.
To use the `Connection` class, it should be extended and the extending
class should implement the on*() event handlers.
Example of an echo server (sends back what it receives):
>>> import twspy
>>> class EchoConnection(twspy.Connection):
>>> def onopen(self):
>>> print 'Connection opened at %s:%d' % self.sock.getpeername()
>>> def onmessage(self, message):
>>> print 'Received message "%s"' % message.payload
>>> self.send(twspy.TextMessage(message.payload))
>>> def onclose(self, message):
>>> print 'Connection closed'
>>> server = twspy.websocket()
>>> server.bind(('', 8000))
>>> server.listen()
>>> while True:
>>> client, addr = server.accept()
>>> EchoConnection(client).receive_forever()
"""
def __init__(self, sock):
"""
......
......@@ -18,17 +18,18 @@ class Server(object):
Example usage:
>>> import twspy
>>> class GameServer(twspy.Server):
>>> class EchoServer(twspy.Server):
>>> def onopen(self, client):
>>> # client connected
>>> def onclose(self, client):
>>> # client disconnected
>>> print 'Client %s connected' % client
>>> def onmessage(self, client, message):
>>> # handle message from client
>>> print 'Received message "%s"' % message.payload
>>> client.send(twspy.TextMessage(message.payload))
>>> def onclose(self, client):
>>> print 'Client %s disconnected' % client
>>> GameServer(8000).run()
>>> EchoServer(8000).run()
"""
def __init__(self, port, hostname='', loglevel=logging.INFO, protocols=[],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment