Tonight, I hope to evaluate how much detail I ought to devote to websockets in Dart for Hipsters. Currently, I plan to mention them in passing in a high-level HTML5 introduction, but perhaps they are worth more.
I normally use faye for my websocket needs, but that won't be of much use to me in Dart as I would have to implement the client-side library. That seems... involved. I briefly explore writing a server in Dart itself (the HTTP server from this dartlang.org article works nicely), but unfortunately websockets are not available on the server-side. Per a tracker issue, websockets are not available in
dart:io and dart:html is not available in server-side dart.So I stick with what I know and install a node.js + express.js server. Along with that, I install WebSocket-Node as it seems to be a solid pure WebSocket implementation. The package.json for my sample app is:
{
"name": "dart-sockets"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.2"
, "jade": ">= 0.0.1"
, "websocket": ">0"
}
}With that, can npm install to get all of the dependencies resolved. The app.js express.js server is just a static file server along with some development (i.e. not origin restricted) WebSocket stuff:var express = require('express'),
WebSocketServer = require('websocket').server;
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.listen(3000);
wsServer = new WebSocketServer({
httpServer: app,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: true
});
wsServer.on('request', function(request) {
var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
Again, that is a lot of code, but most of it is boilerplate express.js for static sites and a stripped down WebSocket server copied from the WebSocket-node documentation. Now for the dart client. I try
#import('dart:html');
main() {
WebSocket ws = new WebSocket("ws://localhost:3000");
}But am greeted with:Internal error: 'http://localhost:3000/main.dart': Error: line 6 pos 22: interface 'WebSocket' has no constructor named 'WebSocket'
var mySocket = new WebSocket("ws://localhost:3000");
^Bummer. It seems that I am stuck with dart:dom:#import('dart:html');
main() {
WebSocket ws = new WebSocket("ws://localhost:3000");
}
That at least compiles, so I try sending a mesage:#import('dart:dom');
main() {
WebSocket ws = new WebSocket("ws://localhost:3000");
ws.addEventListener('open', (event) {
ws.send("Hello");
print("Sent");
});
}But that fails. I see not errors in the client, but no messages logged on the server side. I am forced to call it a night here. I will pick back up tomorrow -- hopefully I can see this through. Regardless, since WebSocket is not yet implemented in dart:html, it seems as though WebSockets can wait until the 1.1 edition of the book.Day #323
Hello Chris,
ReplyDeleteI filed a WebSocket bug against Dart a while ago:
http://code.google.com/p/dart/issues/detail?id=553
Looks like that bug can be closed. I tried a recent build and am able to construct websockets from dart:html: http://japhr.blogspot.com/2012/03/dart-websockets-take-2.html (toward the bottom of that post).
Delete