Introduction
UnittWebSocketClient is an API that allows you to use web sockets in your iOS Objective-C projects. It conforms to the initial & latest versions of web sockets. Simply import WebSocket.h.
There are many different web socket servers out there and many to do not conform to the more recent versions of the specification. Please make sure you are using the correct client version for your server version. If you need a version prior to the hybi drafts, import WebSocket00.h.
The client API tries to follow the client specification from javascript using Objective-C constructs. Web sockets provide a low latency, bi-directional, full-duplex communication channel over TCP. The new draft version of the specification allows for text messages (must be UTF-8), as well as, binary messages. For more information, see Wikipedia.
Setup Your Project
- Include the CFNetwork and Security frameworks
- Add the "-all_load" flag to your "Other Linker Flags" in the "Build Settings" of your project
- Include the UnittWebSocketClient library in your project. For more information on this, see Including a LIbrary in Your Xcode Project.
Using a Web Socket
1. The first step is to create your WebSocketDelegate. This is the class that will receive the callbacks from the web socket.
MyWebSocket.h
#import "WebSocket.h"
@interface MyWebSocket : NSObject <WebSocketDelegate>
{
}
@end
MyWebSocket.m
#import "MyWebSocket.h"
@implementation MyWebSocket
#pragma mark Web Socket
/**
* Called when the web socket connects and is ready for reading and writing.
**/
- (void) didOpen
{
NSLog(@"Socket is open for business.");
}
/**
* Called when the web socket closes. aError will be nil if it closes cleanly.
**/
- (void) didClose:(NSUInteger) aStatusCode message:(NSString*) aMessage error:(NSError*) aError
{
NSLog(@"Oops. It closed.");
}
/**
* Called when the web socket receives an error. Such an error can result in the
socket being closed.
**/
- (void) didReceiveError:(NSError*) aError
{
NSLog(@"Oops. An error occurred.");
}
/**
* Called when the web socket receives a message.
**/
- (void) didReceiveTextMessage:(NSString*) aMessage
{
//Hooray! I got a message to print.
NSLog(@"Did receive message: %@", aMessage);
}
/**
* Called when the web socket receives a message.
**/
- (void) didReceiveBinaryMessage:(NSData*) aMessage
{
//Hooray! I got a binary message.
}
/**
* Called when pong is sent... For keep-alive optimization.
**/
- (void) didSendPong:(NSData*) aMessage
{
NSLog(@"Yay! Pong was sent!");
}
@end
2. The next step is to actually create and use our web socket.
MyWebSocket.h
#import "WebSocket.h"
@interface MyWebSocket : NSObject <WebSocketDelegate>
{
@private
WebSocket* ws;
}
@property (nonatomic, readonly) WebSocket* ws;
- (void) startMyWebSocket;
@end
MyWebSocket.m
//...
@synthesize ws;
#pragma mark Web Socket
- (void) startMyWebSocket
{
[self.ws open];
//continue processing other stuff
//...
}
#pragma mark Lifecycle
- (id)init
{
self = [super init];
if (self)
{
//make sure to use the right url, it must point to your specific web socket endpoint or the handshake will fail
//create a connect config and set all our info here
WebSocketConnectConfig* config = [WebSocketConnectConfig configWithURLString:@"ws://localhost:8080/testws/ws/test" origin:nil protocols:nil tlsSettings:nil headers:nil verifySecurityKey:YES extensions:nil ];
config.closeTimeout = 15.0;
config.keepAlive = 15.0; //sends a ws ping every 15s to keep socket alive
//setup dispatch queue for delegate logic (not required, the websocket will create its own if not supplied)
dispatch_queue_t delegateQueue = dispatch_queue_create("myWebSocketQueue", NULL);
//open using the connect config, it will be populated with server info, such as selected protocol/etc
ws = [[WebSocket webSocketWithConfig:config queue:delegateQueue delegate:self] retain];
//release queue, it is retained by the web socket
dispatch_release(delegateQueue);
}
return self;
}
- (void)dealloc
{
[ws release];
[super dealloc];
}
//...
3. The final step is to call our code.
MyWebSocket* myWS = [[MyWebSocket alloc] init];
[myWS startMyWebSocket];
//continue processing
//...
More Info
- Check out the WebSocket.h for more information on how to use these classes.
- For more information on web sockets, see Wikipedia
Sample Code
You can check out the UnittWebSocketClientTests class for sample code on connecting and talking to a web socket. You can also run your own server for the test using the testws project. To start the server using maven type "mvn jetty:run" at the command line.
WebSocket v00
WebSocket00.h is based on an earlier specification that was not as clear on how binary messages were handled. Therefore, this class only supports UTF8 text messages, so there is only send: and didReceiveMessage: instead of the text/binary variants. If you need the hixie76 keys, you can set the useKeys property to true. Otherwise, everything should just work. You can check out the UnittWebSocketClient00Tests class for sample code for more info on using this version. This version is deprecated in the library and will not be updated as the specification is now 13 versions ahead of this. Contributions to the code will be reviewed and accepted, but there is no planned development due to its incompatibility with the current version of the specification.