| SocketRocket Objective-C WebSocket Client (beta) |
| ================================================ |
| A conforming WebSocket (`RFC 6455 <http://tools.ietf.org/html/rfc6455>`_) |
| client library. |
| |
| `Test results for SocketRocket here <http://square.github.com/SocketRocket/results/>`_. |
| You can compare to what `modern browsers look like here |
| <http://www.tavendo.de/autobahn/testsuite/report/clients/index.html>`_. |
| |
| SocketRocket currently conforms to all ~300 of `Autobahn |
| <http://autobahn.ws/testsuite/>`_'s fuzzing tests (aside from |
| two UTF-8 ones where it is merely *non-strict*. tests 6.4.2 and 6.4.4) |
| |
| Features/Design |
| --------------- |
| - TLS (wss) support. It uses CFStream so we get this for *free* |
| - Uses NSStream/CFNetworking. Earlier implementations used ``dispatch_io``, |
| however, this proved to be make TLS nearly impossible. Also I wanted this to |
| work in iOS 4.x. (SocketRocket only supports 5.0 and above now) |
| - Uses ARC. It uses the 4.0 compatible subset (no weak refs). |
| - Seems to perform quite well |
| - Parallel architecture. Most of the work is done in background worker queues. |
| - Delegate-based. Had older versions that could use blocks too, but I felt it |
| didn't blend well with retain cycles and just objective C in general. |
| |
| Changes |
| ------- |
| |
| v0.3.1-beta2 - 2013-01-12 |
| ````````````````````````` |
| |
| - Stability fix for ``closeWithCode:reason:`` (Thanks @michaelpetrov!) |
| - Actually clean up the NSStreams and remove them from their runloops |
| - ``_SRRunLoopThread``'s ``main`` wasn't correctly wrapped with |
| ``@autoreleasepool`` |
| |
| v0.3.1-beta1 - 2013-01-12 |
| ````````````````````````` |
| |
| - Cleaned up GCD so OS_OBJECT_USE_OBJC_RETAIN_RELEASE is optional |
| - Removed deprecated ``dispatch_get_current_queue`` in favor of ``dispatch_queue_set_specific`` and ``dispatch_get_specific`` |
| - Dropping support for iOS 4.0 (it may still work) |
| |
| |
| Installing (iOS) |
| ---------------- |
| There's a few options. Choose one, or just figure it out |
| |
| - You can copy all the files in the SocketRocket group into your app. |
| - Include SocketRocket as a subproject and use libSocketRocket |
| |
| If you do this, you must add -ObjC to your "other linker flags" option |
| |
| - For OS X you will have to repackage make a .framework target. I will take |
| contributions. Message me if you are interested. |
| |
| |
| Depending on how you configure your project you may need to ``#import`` either |
| ``<SocketRocket/SRWebSocket.h>`` or ``"SRWebSocket.h"`` |
| |
| Framework Dependencies |
| `````````````````````` |
| Your .app must be linked against the following frameworks/dylibs |
| |
| - libicucore.dylib |
| - CFNetwork.framework |
| - Security.framework |
| - Foundation.framework |
| |
| Installing (OS X) |
| ----------------- |
| SocketRocket now has (64-bit only) OS X support. ``SocketRocket.framework`` |
| inside Xcode project is for OS X only. It should be identical in function aside |
| from the unicode validation. ICU isn't shipped with OS X which is what the |
| original implementation used for unicode validation. The workaround is much |
| more rudimentary and less robust. |
| |
| 1. Add SocketRocket.xcodeproj as either a subproject of your app or in your workspace. |
| 2. Add ``SocketRocket.framework`` to the link libraries |
| 3. If you don't have a "copy files" step for ``Framework``, create one |
| 4. Add ``SocketRocket.framework`` to the "copy files" step. |
| |
| API |
| --- |
| The classes |
| |
| ``SRWebSocket`` |
| ``````````````` |
| The Web Socket. |
| |
| .. note:: ``SRWebSocket`` will retain itself between ``-(void)open`` and when it |
| closes, errors, or fails. This is similar to how ``NSURLConnection`` behaves. |
| (unlike ``NSURLConnection``, ``SRWebSocket`` won't retain the delegate) |
| |
| What you need to know |
| |
| .. code-block:: objective-c |
| |
| @interface SRWebSocket : NSObject |
| |
| // Make it with this |
| - (id)initWithURLRequest:(NSURLRequest *)request; |
| |
| // Set this before opening |
| @property (nonatomic, assign) id <SRWebSocketDelegate> delegate; |
| |
| - (void)open; |
| |
| // Close it with this |
| - (void)close; |
| |
| // Send a UTF8 String or Data |
| - (void)send:(id)data; |
| |
| @end |
| |
| ``SRWebSocketDelegate`` |
| ``````````````````````` |
| You implement this |
| |
| .. code-block:: objective-c |
| |
| @protocol SRWebSocketDelegate <NSObject> |
| |
| - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message; |
| |
| @optional |
| |
| - (void)webSocketDidOpen:(SRWebSocket *)webSocket; |
| - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; |
| - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean; |
| |
| @end |
| |
| Known Issues/Server Todo's |
| -------------------------- |
| - Needs auth delegates (like in NSURLConnection) |
| - Move the streams off the main runloop (most of the work is backgrounded uses |
| GCD, but I just haven't gotten around to moving it off the main loop since I |
| converted it from dispatch_io) |
| - Re-implement server. I removed an existing implementation as well because it |
| wasn't being used and I wasn't super happy with the interface. Will revisit |
| this. |
| - Separate framer and client logic. This will make it nicer when having a |
| server. |
| |
| Testing |
| ------- |
| Included are setup scripts for the python testing environment. It comes |
| packaged with vitualenv so all the dependencies are installed in userland. |
| |
| To run the short test from the command line, run:: |
| |
| make test |
| |
| To run all the tests, run:: |
| |
| make test_all |
| |
| The short tests don't include the performance tests. (the test harness is |
| actually the bottleneck, not SocketRocket). |
| |
| The first time this is run, it may take a while to install the dependencies. It |
| will be smooth sailing after that. After the test runs the makefile will open |
| the results page in your browser. If nothing comes up, you failed. Working on |
| making this interface a bit nicer. |
| |
| To run from the app, choose the ``SocketRocket`` target and run the test action |
| (``cmd+u``). It runs the same thing, but makes it easier to debug. There is |
| some serious pre/post hooks in the Test action. You can edit it to customize |
| behavior. |
| |
| .. note:: Xcode only up to version 4.4 is currently supported for the test |
| harness |
| |
| TestChat Demo Application |
| ------------------------- |
| SocketRocket includes a demo app, TestChat. It will "chat" with a listening |
| websocket on port 9900. |
| |
| It's a simple project. Uses storyboard. Storyboard is sweet. |
| |
| |
| TestChat Server |
| ``````````````` |
| We've included a small server for the chat app. It has a simple function. |
| It will take a message and broadcast it to all other connected clients. |
| |
| We have to get some dependencies. We also want to reuse the virtualenv we made |
| when we ran the tests. If you haven't run the tests yet, go into the |
| SocketRocket root directory and type:: |
| |
| make test |
| |
| This will set up your `virtualenv <http://pypi.python.org/pypi/virtualenv>`_. |
| Now, in your terminal:: |
| |
| source .env/bin/activate |
| pip install git+https://github.com/facebook/tornado.git |
| |
| In the same terminal session, start the chatroom server:: |
| |
| python TestChatServer/py/chatroom.py |
| |
| There's also a Go implementation (with the latest weekly) where you can:: |
| |
| cd TestChatServer/go |
| go run chatroom.go |
| |
| Chatting |
| ```````` |
| Now, start TestChat.app (just run the target in the XCode project). If you had |
| it started already you can hit the refresh button to reconnect. It should say |
| "Connected!" on top. |
| |
| To talk with the app, open up your browser to `http://localhost:9000 <http://localhost:9000>`_ and |
| start chatting. |
| |
| |
| WebSocket Server Implementation Recommendations |
| ----------------------------------------------- |
| SocketRocket has been used with the following libraries: |
| |
| - `Tornado <https://github.com/facebook/tornado>`_ |
| - Go's `WebSocket package <http://godoc.org/code.google.com/p/go.net/websocket>`_ or Gorilla's `version <http://www.gorillatoolkit.org/pkg/websocket>`_ |
| - `Autobahn <http://www.tavendo.de/autobahn/testsuite.html>`_ (using its fuzzing |
| client) |
| |
| The Tornado one is dirt simple and works like a charm. (`IPython notebook |
| <http://ipython.org/ipython-doc/dev/interactive/htmlnotebook.html>`_ uses it |
| too). It's much easier to configure handlers and routes than in |
| Autobahn/twisted. |
| |
| As far as Go's goes, it works in my limited testing. I much prefer go's |
| concurrency model as well. Try it! You may like it. |
| It could use some more control over things such as pings, etc., but I |
| am sure it will come in time. |
| |
| Autobahn is a great test suite. The Python server code is good, and conforms |
| well (obviously). However for me, twisted would be a deal-breaker for writing |
| something new. I find it a bit too complex and heavy for a simple service. If |
| you are already using twisted though, Autobahn is probably for you. |
| |
| Contributing |
| ------------ |
| Any contributors to the master SocketRocket repository must sign the `Individual |
| Contributor License Agreement |
| (CLA) |
| <https://spreadsheets.google.com/spreadsheet/viewform?formkey=dDViT2xzUHAwRkI3X3k5Z0lQM091OGc6MQ&ndplr=1>`_. |
| It's a short form that covers our bases and makes sure you're eligible to |
| contribute. |
| |
| When you have a change you'd like to see in the master repository, `send a pull |
| request <https://github.com/square/SocketRocket/pulls>`_. Before we merge your |
| request, we'll make sure you're in the list of people who have signed a CLA. |