浏览代码

Updated README

Taddeus Kroes 11 年之前
父节点
当前提交
d4c3c56444
共有 1 个文件被更改,包括 121 次插入75 次删除
  1. 121 75
      README.md

+ 121 - 75
README.md

@@ -11,10 +11,11 @@ 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:
+Here 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").
+- Building custom frames (see "Sending frames with a websocket").
+- Messages, which are higher-level than frames (see "Sending messages with a a
+  connection").
 - Connections, which hide the handling of control frames and automatically
   concatenate fragmented messages to individual payloads.
 - HTTP authentication during handshake.
@@ -24,98 +25,137 @@ Her is a quick overview of the features in this library:
   [deflate-frame](http://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06)
   and
   [permessage-deflate](http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-17).
-- Asynchronous sockets with an EPOLL-based server.
+- Threaded and asynchronous (EPOLL-based) server implementations.
 
 
 Installation
 ============
 
-Use Python's package manager:
+Using Python's package manager (note: this seems to be bugged atm):
 
     easy_install wspy
     pip install wspy
 
+Using Git inside your project:
 
-Basic usage
-===========
+    git submodule add https://github.com/taddeus/wspy.git
 
-- 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:
+Getting Started
+===============
 
-        import wspy, socket
-        sock = wspy.websocket()
-        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        sock.bind(('', 8000))
-        sock.listen(5)
+The following example is an echo server (sends back what it receives) and can
+be used out of the box to connect with a browser. The API is similar to that of
+web sockets in JavaScript:
 
-        client = sock.accept()
-        client.send(wspy.Frame(wspy.OPCODE_TEXT, 'Hello, Client!'))
-        frame = client.recv()
+    import logging
+    import wspy
 
-  Client example:
+    class EchoServer(wspy.AsyncServer):
+        def onopen(self, client):
+            print 'Client %s connected' % client
 
-        import wspy
-        sock = wspy.websocket(location='/my/path')
-        sock.connect(('', 8000))
-        sock.send(wspy.Frame(wspy.OPCODE_TEXT, 'Hello, Server!'))
+        def onmessage(self, client, message):
+            print 'Received message "%s"' % message.payload
+            client.send(wspy.TextMessage(message.payload))
 
-- A `Connection` instance represents a connection between two end points, based
-  on a `websocket` instance. A connection handles control frames properly, and
-  sends/receives messages (`Message` instances, which are higher-level than
-  frames). Messages are automatically converted to frames, and received frames
-  are converted to messages. Fragmented messages (messages consisting of
-  multiple frames) are also supported.
+        def onclose(self, client, code, reason):
+            print 'Client %s disconnected' % client
 
-  Example of an echo server (sends back what it receives):
+    EchoServer(('', 8000),
+               extensions=[wspy.DeflateMessage(), wspy.DeflateFrame()],
+               loglevel=logging.DEBUG).run()
 
-        import socket
-        import wspy
+Corresponding client code (JavaScript, run in browser):
 
-        class EchoConnection(wspy.Connection):
-            def onopen(self):
-                print 'Connection opened at %s:%d' % self.sock.getpeername()
+    ws = new WebSocket('ws://localhost:8000');
+    ws.onopen = function() {
+        console.log('open');
+        this.send('Hello, World!');
+    };
+    ws.onmessage = function(e) {
+        console.log('message', e.data);
+    };
+    ws.onerror = function() {
+        console.log('error');
+    };
+    ws.onclose = function(e) {
+        console.log('close', e.code, e.reason);
+    };
 
-            def onmessage(self, message):
-                print 'Received message "%s"' % message.payload
-                self.send(wspy.TextMessage(message.payload))
 
-            def onclose(self, code, reason):
-                print 'Connection closed'
+Sending frames with a websocket
+===============================
 
-        server = wspy.websocket()
-        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-        server.bind(('', 8000))
-        server.listen(5)
+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).
 
-        while True:
-            client, addr = server.accept()
-            EchoConnection(client).receive_forever()
+Server example:
 
-  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.
+    import wspy, socket
+    sock = wspy.websocket()
+    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    sock.bind(('', 8000))
+    sock.listen(5)
 
-  **Note:** For browser clients, you will probably want to use JSON encoding.
-  This could, for example, be implemented as follows:
+    client = sock.accept()
+    client.send(wspy.Frame(wspy.OPCODE_TEXT, 'Hello, Client!'))
+    frame = client.recv()
 
-        import wspy, json
+Client example:
 
-        def msg(**data):
-            return wspy.TextMessage(json.dumps(data))
+    import wspy
+    sock = wspy.websocket(location='/my/path')
+    sock.connect(('', 8000))
+    sock.send(wspy.Frame(wspy.OPCODE_TEXT, 'Hello, Server!'))
 
-        # create some connection `conn`...
 
-        conn.send(msg(foo='Hello, World!'))
+Sending messages with a connection
+==================================
 
+A `Connection` instance represents a connection between two end points, based
+on a `websocket` instance. A connection handles control frames properly, and
+sends/receives messages (`Message` instances, which are higher-level than
+frames). Messages are automatically converted to frames, and received frames
+are converted to messages. Fragmented messages (messages consisting of
+multiple frames) are also supported.
 
-Built-in servers
-================
+Example of an echo server (sends back what it receives):
+
+    import socket
+    import wspy
+
+    class EchoConnection(wspy.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(wspy.TextMessage(message.payload))
+
+        def onclose(self, code, reason):
+            print 'Connection closed'
+
+    server = wspy.websocket()
+    server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+    server.bind(('', 8000))
+    server.listen(5)
+
+    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.
+
+
+Managing connections with a server
+==================================
 
 Threaded
 --------
@@ -131,26 +171,26 @@ also receive an additional `client` argument. The client argumetn is a modified
 
 For example, the `EchoConnection` example above can be rewritten to:
 
-      import wspy
+    import wspy
 
-      class EchoServer(wspy.Server):
-          def onopen(self, client):
-              print 'Client %s connected' % client
+    class EchoServer(wspy.Server):
+        def onopen(self, client):
+            print 'Client %s connected' % client
 
-          def onmessage(self, client, message):
-              print 'Received message "%s"' % message.payload
-              client.send(wspy.TextMessage(message.payload))
+        def onmessage(self, client, message):
+            print 'Received message "%s"' % message.payload
+            client.send(wspy.TextMessage(message.payload))
 
-          def onclose(self, client, code, reason):
-              print 'Client %s disconnected' % client
+        def onclose(self, client, code, reason):
+            print 'Client %s disconnected' % client
 
-      EchoServer(('', 8000)).run()
+    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.
 
-Asynchronous
-------------
+Asynchronous (recommended)
+--------------------------
 
 The `AsyncServer` class has the same API as `Server`, but uses
 [EPOLL](https://docs.python.org/2/library/select.html#epoll-objects) instead of
@@ -164,3 +204,9 @@ Extensions
 ==========
 
 TODO
+
+
+Secure sockets with SSL
+=======================
+
+TODO