11. HTTP Websocket
GET wss://socket.artoo.in/chat?
GET /home HTTP/1.1 username=admin&clientId=0782cd45-307d-414b-8efa-b2156253b6xx
Host: trial.artoo.in HTTP/1.1
Connection: keep-alive Origin: https://trial.artoo.in
Cache-Control: max-age=0 Cookie: ...
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) __utma=27942636.1788801618.1323048033.1337320289.1337406233.26
AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.46 5; __utmb=27942636.7.10.1337406233; __utmc=27942636;
Safari/536.5 __utmz=27942636.1337136927.261.12.utmcsr=google|
Accept: text/html,application/xhtml+xml,application/ utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
xml;q=0.9,*/*;q=0.8 Connection: Upgrade
Accept-Encoding: gzip,deflate,sdch Sec-WebSocket-Extensions: x-webkit-deflate-frame
Accept-Language: en-US,en;q=0.8 Host: socket.artoo.in
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 Sec-WebSocket-Key: ego8R97Ruc3d5RPwRhhtzw==
Cookie: ....... Upgrade: websocket
Sec-WebSocket-Version: 13
HTTP/1.1 200 OK
Date: Sat, 19 May 2012 06:04:24 GMT
Server: Play! Framework;master-jenkins-Artoo-Play-15;prod
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Set-Cookie: ..... HTTP/1.1 101 Switching Protocols
. Connection: Upgrade
. Upgrade: websocket
. Sec-WebSocket-Accept: CEbdJJgOTp1ZCcx6+RZTngrI5Ek=
Via: 1.1 artoo.in
Vary: Accept-Encoding
Content-Encoding: gzip
Connection: close
Transfer-Encoding: chunked
One time
Everytime (2 bytes of overhead for every
message)
12. "Reducing kilobytes of data to 2 bytes…and
reducing latency from 150ms to 50ms is far
more than marginal. In fact, these two factors
alone are enough to make Web Sockets
seriously interesting to Google."
- Ian Hickson (Google’s HTML5 Spec Lead)
13. Specs
• Based on TCP but not true TCP socket
• ws:// or wss://
• Full-Duplex
• Both UTF-8 strings and binary frame can
be sent in any direction
• More at http://dev.w3.org/html5/
websockets/
17. Android Java Websocket https://github.com/TooTallNate/Java-WebSocket
Client-Side
@Override
public class SampleSocket extends WebSocketClient { public void onMessage(String message) {
Chat chat = Chat.fromJSON(message);
private Context context;
private boolean connected = false; if (chat != null) {
private Handler h = new Handler(); ContentValues values = new ContentValues();
private Runnable r = new Runnable() {
switch (chat.event) {
@Override case ONLINE:
public void run() {
try { break;
Chat chat = new Chat(); case OFFLINE:
chat.event = event_type.STAY_ALIVE;
if (connected) { break;
send(chat.toJSON()); case USER:
}
} catch (IOException e) { break;
e.printStackTrace(); case MESSAGE:
}
break;
h.postDelayed(r, 10000); default:
}
}; }
public SampleSocket(Context context, URI serverUri) { // Insert / Update into DB
super(serverUri); }
this.context = context;
}
// Sending keep alive messages
h.postDelayed(r, 5000); @Override
} public void onOpen() {
public SampleSocket(Context context, URI serverUri, }
WebSocketDraft draft) {
super(serverUri, draft); @Override
this.context = context; public void onClose() {
}
}
@Override
public void onIOError(IOException ex) {
}
18. Android Client-Side
Activity 1
Use Messenger
Service
Activity 2
WebSocket
19. Java jquery-websocket
http://jwebsocket.org/
Server-Side
public class JWebSocketTokenListenerSample implements WebSocketTokenListener {
private static Logger log = Logging.getLogger(JWebSocketTokenListenerSample.class);
public void processOpened(WebSocketEvent aEvent) {
log.info("Client '" + aEvent.getSessionId() + "' connected.");
}
public void processPacket(WebSocketEvent aEvent, WebSocketPacket aPacket) {
// here you can process any non-token low level message, if desired
}
public void processToken(WebSocketTokenEvent aEvent, Token aToken) {
log.info("Client '" + aEvent.getSessionId() + "' sent Token: '" + aToken.toString() + "'.");
// here you can interpret the token type sent from the client according to your needs.
String lNS = aToken.getNS();
String lType = aToken.getType();
// check if token has a type and a matching namespace
if (lType != null && "my.namespace".equals(lNS)) {
// create a response token
Token lResponse = aEvent.createResponse(aToken);
if ("getInfo".equals(lType)) {
// if type is "getInfo" return some server information
lResponse.put("vendor", JWebSocketConstants.VENDOR);
lResponse.put("version", JWebSocketConstants.VERSION_STR);
lResponse.put("copyright", JWebSocketConstants.COPYRIGHT);
lResponse.put("license", JWebSocketConstants.LICENSE);
} else {
// if unknown type in this namespace, return corresponding error message
lResponse.put("code", -1);
lResponse.put("msg", "Token type '" + lType + "' not supported in namespace '" + lNS + "'.");
}
aEvent.sendToken(lResponse);
}
}
public void processClosed(WebSocketEvent aEvent) {
log.info("Client '" + aEvent.getSessionId() + "' disconnected.");
}
}
21. ChatRoom room = ChatRoom.get(roomNo);
// Socket connected, join the chat room
EventStream<ChatRoom.Event> roomMessagesStream = room.join(user);
// Loop while the socket is open
while (inbound.isOpen()) {
// Wait for an event (either something coming on the inbound
// socket channel, or ChatRoom messages)
Either<WebSocketEvent, ChatRoom.Event> e = await(Promise
.waitEither(inbound.nextEvent(),
roomMessagesStream.nextEvent()));
// Case: User typed 'quit'
for (String userMessage : TextFrame.and(Equals("quit")).match(
e._1)) {
room.leave(user);
outbound.send("quit:ok");
disconnect(); // Case: Someone joined the room
} for (ChatRoom.Join joined : ClassOf(ChatRoom.Join.class).match(
e._2)) {
// Case: TextEvent received on the socket
outbound.send("join:%s", joined.user);
for (String userMessage : TextFrame.match(e._1)) {
}
room.say(user, userMessage);
} // Case: New message on the chat room
for (ChatRoom.Message message : ClassOf(ChatRoom.Message.class)
.match(e._2)) {
outbound.send("message:%s:%s", message.user, message.text);
}
// Case: Someone left the room
for (ChatRoom.Leave left : ClassOf(ChatRoom.Leave.class).match(
e._2)) {
outbound.send("leave:%s", left.user);
}
// Case: The socket has been closed
for (WebSocketClose closed : SocketClosed.match(e._1)) {
room.leave(user);
disconnect();
}
}
22. Don’t Even...
• Nginx
• Use HA Proxy / Varnish ahead of nginx
• Auto Manual STAY_ALIVE
• Combine REST & Websocket Servers
• REST = Stateless
• WebSockets = State-ful